#ifndef PLC_LICENCE1_COMMON_H
#define PLC_LICENCE1_COMMON_H

#include "utils.h"
#ifndef EZ_APPLICATION_LICENCE_DISABLE

#include <vector>
#include "licenceCommon.h"
#include "SDCard.h"

/// @brief společná třída pro reader a generátor ELC1
class LicenceELC1
{
public:
  LicenceELC1();
  LicenceELC1(LicenceIdentification &licIdentification);
  ~LicenceELC1();

  bool getSDData();                       // reads SD card
  string getLicenceName(BYTE licPostfix); // get proper licencename
  string getLicenceName();
  void initCrypto();
  LicenceIdentification lIdentification;

  string cid_cdsPath = "";
  string licenceFilePath = "";

  Mapping mapping;

  ErrorMessage errorMessage;

#define MAX_LICENCE_COUNT 100

  enum InputLicenceType
  {
    EOSEOV = 1
  };

  enum BinaryGenerationType
  {
    Base64Cout = 1,
    File = 2
  };

  enum PlcLicenceType
  {
    LicenceOther = 0,
    LicenceEov = 1
  };
  enum LidIdType
  {
    Ddts = 1,
    EovOsv = 2
  };
  enum PrefixType
  {
    ELC1 = 1
  };

  typedef uint32_t DWORD;
  typedef uint16_t WORD;
  typedef uint8_t BYTE;
  typedef uint32_t UDINT;
  typedef uint32_t DATE;
  typedef uint8_t USINT;
  typedef int32_t DINT;
  typedef uint16_t UINT;
  typedef int16_t INT;

  /// @brief identifikace licence
  typedef struct LicenceIdent
  {
    WORD licPrefixType = 0; // WORD;	typ licencniho souboru - pro kazdy prefig je jiny typ souboru a jiny zpusob zpracovani dat [sifrovani, podpis, komprese, ...]
    WORD licHeaderType = 0; //: WORD;	typ hlavicky kriptovane casti licencniho souboru
    WORD licDataType = 0;   //: WORD;	typ licence - pro kazdou hlavicku jsou samostatne typy licenci - mohou byt i shodne s typem jine hlavicky
    WORD licSubType = 0;    //: WORD;	slouceny typ hlavicku a typ licence => typ hlavicky * 256 + typ licence
    WORD licIDType = 0;     //: WORD;	id aplikace, pro kterou je licence urcena => 1 = ddts, 2 = eov-osv
    BYTE licPostfix = 0;    //: BYTE;	rozliseni licence pro stejny typ - napr. pokud mam 2x SW pro DRT na 2 nezavisle ED
  } LicenceIdent;

  /// @brief struktura pro přípravu dat na generování
  typedef struct LicenceSourceData
  {

    BYTE startGen; // na nabeznou hranu se vygeneruje licence
    BYTE loadSD;   //: BOOL; na nabeznou hranu se nacte SD karta
    // zadavane hodnoty
    BYTE licType_id;               // vybrany typ licence
    char licDescription1[40] = {}; //: STRING(39); jmeno stanice
    char licDescription2[20] = {}; //: STRING(19); jmeno rozvadece
    BYTE licPostfix;               //	rozliseni licence pro stejny typ - napr. pokud mam 2x SW pro DRT na 2 nezavisle ED
    BYTE enInit;                   //: BOOL; inicializace (promazani) adresare pro licence
    // interne generovane hodnoty
    WORD licType;           //: WORD;	hlavicka licence
    BYTE licIdOk;           //: BOOL;	korektne zvoleny typ licence
    string licPostfixIdent; //[2]; //: STRING(2); vygenerovany postfix z cisla pro rozliseni postfixu v souborech a textech
  } LicenceSourceData;

  /// @brief struktura obsahující dodatečné informace k licenci
  typedef struct PlcData
  {
    string plcType = "";
    string licenceType = ""; // typ
    string licenceVersion = "1";
    string licenceName = ""; // název
    string station = "";     // stanice
    string distributor = ""; // rozvadec
  } PlcData;

  /*
  MID (Manufacturer ID): 8 bits - Identifies the manufacturer of the SD card.
  OID (OEM/Application ID): 16 bits - Identifies the OEM and application-specific information.
  PNM (Product Name): 40 bits - A string representing the product name of the SD card.
  PRV (Product Revision): 8 bits - The product revision/version.
  PSN (Product Serial Number): 32 bits - A unique serial number assigned to the SD card during manufacturing.
  MDT (Manufacturing Date): 12 bits - Represents the manufacturing date of the SD card.
  CRC (CRC7 Checksum): 7 bits - A cyclic redundancy check for error detection.
  unused: 4 bits - Reserved for future use.
  */

  /// @brief struktura pro načtení CIS a CSD dat
  typedef struct SDData
  {
    BYTE isCorrectLoad = 0;    // SD karta je korektne nactena //bool vs byte ?
    BYTE CID_nibble[32] = {0}; // surova data CID ze souboru
    BYTE CID[16] = {0};        //  prekodovane CID informace
    BYTE manufacturerID = 0;   // ID vyrobce 1B -> Byte 15
    char oemID[2] = {};        // ID aplikace/oem 2B -> Byte 13-14  // oemID: !!STRING(3);
    char name[5] = {};         // jmeno produktu 5B -> Byte 8-12 !!STRING(6);
    BYTE productRevision_hw = 0;
    BYTE productRevision_sw = 0;
    float productRevision = 0; // revize produktu 1B [bcd sh] -> Byte 7, bity 0-3 = revize HW, bity 4-7 = revize SW
    DWORD serialNumber = 0;    // seriove cislo karty 4B -> Byte 3-6
    WORD manufacturerDate_year = 0;
    BYTE manufacturerDate_month = 0;
    char manufacturerDate[10] = {}; //: STRING(10); // datum vyroby 2B [bcd -yym] -> Byte 1-2, bity 0-3 = mesic, bity 4-11 = posledni cislice roku or roku 2000, bity 12-15 nepouzito
    BYTE CRCOK = 0;                 // CRC 1B -> Byte 0, bity 1-7, bit 0 je vzdy = 1
    BYTE CSD_nibble[32] = {};       //: ARRAY [0..31] OF BYTE;	// surova data CSD ze souboru
    BYTE CSD[16] = {};              //: ARRAY [0..15] OF BYTE;			// prekodovane CSD informace
    UDINT cardSize = 0;             //: UDINT;							// velikost SD karty
    BYTE cardGSize = 0;             // prepocitana velikost na GB
  } CidData;

  // nekodovana cast licence

  /// @brief nekryptovaná hlavička licence
  typedef struct LicenceDataMainHeaderELC
  {
    BYTE licType = 0;
    ; // typ licence => duplicitni polozka s hlavickou kodovane casti licence - pouze pro ucely dekodovani dat
    BYTE dummy1 = 0;
    WORD licSubType = 0;       // horni byte = typ hlavicky kodovane casti, spodni byte = typ dat polozkove casti => duplicitni casti s id a hlavickou kodovane casti - pouze pro ucely dekodovani
    char description[80] = {}; // viditelny popis licincniho souboru
    UDINT sizeData = 0;        // velikost kodovane casti licence v Bytech
  } LicenceDataMainHeaderELC;

  // hlavní struktura licence
  typedef struct LicenceDataMainELC
  {
    // prefix MUSI zustat jako prvni prvek struktury a MUSI byt typu DWORD
    DWORD prefix = 0;                     // urcuje strukturu dat citelne casti licencniho souboru [teto struktury] + zpusob sifrovani, dig, podpis, kompresi... dat
    LicenceDataMainHeaderELC licHeader{}; // nekodovana cast licence
  } LicenceDataMain;

  // polozkova cast licence verze 1.0
  typedef struct LicenceDataItem
  {
    WORD protoId = 0;  // id protokolu pro ktery je licence
    WORD licCount = 0; // pocet datovych bodu licence
    DWORD data1 = 0;   // doplnkove nahodne cislo, slouzi pro overeni licence v runtime
  } LicenceDataItem;

  // identifikace kodovane casti licence - !!! MUSI yustat pro vsechny verze STEJNA !!!
  typedef struct LicenceDataId
  {
    WORD version = 0; // verze hlavicky
    WORD rez = 0;
    UDINT cardSize = 0;
  } LicenceDataId;

  typedef struct LicenceDataHeader
  {
    BYTE licType = 0;              //	typ licence => 0...neznamy (chyba), 1...DDTS, 2...EOV-OSV
    BYTE licReserve = 0;           //	rezerva
    WORD licVersion = 0;           //: WORD; verze polozkove casti licence
    DATE licDate = 0;              // datum vygenerovani licence
    char licDescription1[40] = {}; // licDescription1: STRING(39); stanice, pro kterou byla licence generovana
    char licDescription2[20] = {}; // STRING(19); rozvadec, pro ktery byla licence generovana
    USINT licCount = 0;            //	aktivni pocet dat polozkove casti licence
    BYTE licDummy = 0;             // rezerva
    WORD licReservew = 0;          //	rezerva
  } LicenceDataHeader;

  // kodovana cast licence verze 1.1 s polozkovou casi licence verze 1.0
  typedef struct LicenceData
  {
    LicenceDataId id{}; // id !!! MUSI  zustat na PRVNIM miste struktury
    LicenceDataHeader header{};
    LicenceDataItem items[MAX_LICENCE_COUNT] = {}; // polozkova cast licence
    WORD dummy = 0;                                // pro zarovnani struktur - jinak nebude fungovat vypocet a kontrola CRC !!!
    WORD crc = 0;                                  // kontrolni kod - !!! MUSI zustat na konci struktury
  } LicenceData;

  typedef struct LicenceRetData
  {
    BYTE retCode = 0;      //	navratovy kod funkce pro nacteni SD
    DINT subCode = 0;      //	doplnkova informace chyby
    std::string text = ""; //	textovy popis navratove hodnoty
    bool isDone = false;   // operace korektne dokoncena
  } LicenceRetData;

  typedef struct CryptData
  {
    bool initDone = false;
    DWORD cryptDataAddress = 0;   // adresa na data, ktera se maji cryptovat
    UINT cryptDataSize = 0;       // velikostdat, ktera semaji cryptovat
    BYTE aesInitVector[15] = {0}; //] : ARRAY [0..14] OF BYTE;// AES 128 bit IV
    BYTE aesKey[32] = {0};        // : ARRAY [0..31] OF BYTE;	// AES 256 bit key
    DINT aesRetVal = 0;           // navratova hodnota AES
    DWORD retDataAddress = 0;     // adresa na ulozeni cryptovana dat
    UINT retDataSize = 0;         // velikost cryptovanych dat
    LicenceData *licenseData;
  } CryptData;

  const BYTE licMaxCount = 100;
  const WORD cEzLic_p78ou3_IDType_DDTS = 1;                                           // aplikace DDTS
  const WORD cEzLic_p78ou3_IDType_EOVOSV = 2;                                         // aplikace EOV-OSV
  const WORD cEzLic_p78ou3_IDType_DRT = 3;                                            // aplikace DRT
  const DWORD cEzLic_p78ou3_CheckLicNumber_ERR = 0xFFFFFFFF;                          // 16#FFFFFFFF; // chybna identifikace licence
  const DWORD cEzLic_p78ou3_CheckLicNumber_EOV1 = 3781234965;                         // cislo pro overeni licence EOV, OSV verze 1
  const BYTE cEzLic_p78ou3_CheckLicNumberId_ERR = 0;                                  // id licence pro neidentifikovanou licenci
  const BYTE cEzLic_p78ou3_CheckLicNumberId_EOV1 = 1;                                 // id licence pro EOV, OSV verze 1
  const BYTE cEzLic_p78ou3_MaxCheckLicNumberId = cEzLic_p78ou3_CheckLicNumberId_EOV1; // pocet identifikatoru licenci
  const DWORD cEzLic_p78ou3_CheckLicNumber[2] = {cEzLic_p78ou3_CheckLicNumber_ERR, cEzLic_p78ou3_CheckLicNumber_EOV1};
  const WORD cEzLic_p78ou3_LicPrefixType_ELC1 = 1; //	prefix typ1 = pouze zasifrovani dat
  const WORD cEzLic_p78ou3_HeaderType_10 = 10;     // hlavicka kriptovane casti verze 1.0
  const WORD cEzLic_p78ou3_DataType_10 = 10;       // data licence verze 1.0
  const WORD cEzLic_p78ou3_SubType_10_10 = 0x0A0A; // subtype - verze hlavicky + verze data -> cEzLic_p78ou3_HeaderType_XX * 256 + cEzLic_p78ou3_DataType_XX
  // ID aplikace

  const BYTE cnibblescount11 = 32;

  CryptData cryptData; // structure for encryp
  CidData sdData;      // data loaded from SD card


  SDCard sdCard;

  string cidString = "";
  char cid[32] = {};
  string csdString = "";
  char csd[32] = {};                                                        // CSD
  string stationName;                                                       // name of station
  string distributor;                                                       // name of switch
  const char *dataFileName;                                                 // name of xml containing data (if not taken from commandline)
  WORD licType = 2;                                                         // type of licence
  BinaryGenerationType binaryGeneration = BinaryGenerationType::Base64Cout; // typ generování binárního souboru

  string dataLicenceType = "";         // type of licence from xmlFile;
  string dataLicenceVersion = "";      // version type of licence from xmlFile;
  string dataCryptoVersion = "";       // version of crypting from xmlFile
  string dataGenerationType = "";      // version of dataGeneration from xmlFile
  string dataLicenceDataFileName = ""; // name of licence file to read

  
};

#endif
#endif