#ifndef LICENCE_COMMON_H_
#define LICENCE_COMMON_H_

#include "licConnector.h"
#ifndef EZ_APPLICATION_LICENCE_DISABLE

#define CRC = 1

//---------------- společná hlavička pro všechny licence ----------------

#include <cstring>
#include <string>
#include <unordered_map>
#include <map>
#include <stdint.h>

using namespace std;

#define XML_VERSION 1
#define SOFTWARE_VERSION 1
#define SUCCES 0
#define CRYPT_INIT_VECTOR_SIZE 16
#define CRYPT_INIT_KEY_SIZE 32


const int cidSize = 32;
const int csdSize = 32;
const int generatorVersion = 1;

typedef uint8_t BYTE;
typedef uint16_t WORD;
typedef uint32_t DWORD;
typedef uint32_t DATE;

enum class GeneralError
{
  GeneralError = 1,
  FileOpenError = 2,
  FileReadError = 3,
  FileWriteError = 4,
  ELCNotImplemented = 5,
  LicenceTypeNotImplemented = 6,
  CompatibilityTypeNotImplemented = 7,
  ELCMismatch = 8,
  CRCMismatch = 9,
  EncryptError = 10,
  DecryptError = 11,
  ParamMissing = 12,
  IvanlidParam = 13,
  SDCardReadError = 50,
  LicenceReadError = 51,
  LicenceSizeMismatch = 52,
  LicenceSizeCardMismatch = 53,
  LicenceMismatch = 54,
  LicenceCRCMismatch = 54,
  UIDReadError = 55,
  ItemsCountMismatch = 61
};

enum class ELCType
{
  ELC1 = 1, // starý původní licenční soubor zalozený na CID a CSD
  ELC2 = 2, // modifikovaný starý licenční soubor umoznující modifikace (šifrování, název) dle parametrů
  ELC3 = 3  // budoucí softwarový licenční soubor, který není zalozený na existenci CID a CSD, ale na unikátním ID instalace linuxu
};
enum class ELCSubType
{
  DEFAULT = 1
}; // subtype = dataVersion
enum class LicenceType
{
  EOS_EOV,
  DDTS,
  DRT
}; //
enum class HeaderType
{
  DEFAULT = 0
}; ////subtype = version

enum class EncryptionType
{
  CID_AES256 = 10,
  FIX_AES256 = 20
};
enum class BinaryType
{
  FILE = 1,
  BASE64 = 2
};
enum class PlcType
{
  WAGO = 1,
  TECO = 2
};
enum class FileNameGenerationType
{
  DEFAULT = 1
};

struct CryptInitVector{ int vec[CRYPT_INIT_VECTOR_SIZE]; };
struct CryptAesKey { int key[CRYPT_INIT_KEY_SIZE]; };

// indexy musí být velká písmena ze základní ASCI tabulky
struct Mapping
{
  unordered_map<string, LicenceType> licMapTypes = {{"EOV_OSV", LicenceType::EOS_EOV}, {"DDTS", LicenceType::DDTS}, {"DRT", LicenceType::DRT}};
  unordered_map<string, EncryptionType> licMapEncryption = {{"CID_AES256", EncryptionType::CID_AES256}, {"FIX_AES256", EncryptionType::FIX_AES256}};
  unordered_map<string, PlcType> licMapPlcType = {{"WAGO", PlcType::WAGO}, {"TECO", PlcType::TECO}};
};

struct ErrorMessage
{
  int code = 0;
  string message = "";
};

struct LicenceIdentification
{
  ELCType licElcType = ELCType::ELC2; // hlavní typ licenčního souboru
  LicenceType licLicenceType;
  string licTypeName = "";
  PlcType licPlcType;
  uint8_t licenceVersion = 1; // verze licence, určuje kodování, pojmenování souborů
  uint8_t licenceIndex = 0;   // index licenčního souboru v případě, ze jich je víc
  uint8_t revision;
  uint8_t licCompatibility = 0; // identikator hlavního ELC. 0 = nedefinová a vrací se defaultní k danému ELC
  uint16_t licItemsCount = 0;
  string cid_cds_path = "";
  string licenceFilePath = "";
};

/// @brief obecná struktura pro reader
struct LicenceInfoGeneral
{
  map<DWORD, DWORD> licences = {};
};

/// @brief obecná struktura polozky licence, defaultní kompatibilita
struct LicenceItem
{
  DWORD protocolId{};
  DWORD dataPointsCount{};
};

/* struktury pro ELC 1 */
// defaultní struktura pro ELC 1
struct LicenceELC1Info
{
  bool isValid{false};
};

// struktura ELC1, kompatibilita 1
struct LicenceELC1Info_1
{
  unordered_map<int, int> licences = {};
};

// defaultni struktura polozky licence ELC 1
struct LicenceELC1Item
{
  int protocolId = -1;
  int dataPointsCount = 0;
};

/* struktury pro ELC 2 */
// defaultní struktura pro ELC 2
struct LicenceELC2Info
{
  map<DWORD, DWORD> licences = {};
};

/* struktury pro ELC 3 */
// defaultní struktura pro ELC 3
struct LicenceELC3Info
{
  map<DWORD, DWORD> licences = {};
};

// struct LicenceELC2Info_1
// {
//   map<int, int> licences = {};
// };

// defaultni struktura polozky ELC 2
struct LicenceELC2Item
{
  DWORD protocolId{};
  DWORD dataPointsCount{};
};

// struktura polozky ELC 2 pro další kompatibility
struct LicenceELC2Item_1
{
  DWORD protocolId{};
  DWORD dataPointsCount{};
};

// defaultni struktura polozky ELC 3
struct LicenceELC3Item
{
  DWORD protocolId{};
  DWORD dataPointsCount{};
};

// struktura polozky ELC 3 pro další kompatibility,
struct LicenceELC3Item_1
{
  DWORD protocolId{};
  DWORD dataPointsCount{};
};

class LicenceException : public std::exception
{
public:
  LicenceException(int errorCode, const std::string &errorMessage)
      : errorCode_(errorCode), errorMessage_(errorMessage) {}

  const char *what() const noexcept override
  {
    return errorMessage_.c_str();
  }

  int getErrorCode() const
  {
    return errorCode_;
  }

  const std::string &getErrorMessage() const
  {
    return errorMessage_;
  }

private:
  int errorCode_;
  std::string errorMessage_;
};

#endif

#endif
