#ifndef LICENCE_COMMON_H_
#define LICENCE_COMMON_H_

#include <cstring>
#include <map>
#include "pugixml.hpp"

using namespace std;

#define XML_VERSION 1
#define SOFTWARE_VERSION 1
#define SUCCES 0;

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



enum class GeneralError
{
  GeneralError = 1,
  FileOpenError = 2,
  FileReadError = 3,
  FileWriteError = 4,
  ELCNotImplemented = 5,
  LicenceTypeNotImplemented = 6,
  CompatibilityTypeNotImplemented = 7,
  ELCMismatch = 8,
  CRCMismatch = 9
};

// map<GeneralError, string> mapGeneralErrors = {
//     // 1,"test"
//     // {CommonError::GeneralError, "Obecná chyba."},
//     // {CommonError::FileReadError, "Chyba čtení souboru."},
//     // {CommonError::FileReadError, "Chyba zápisu souboru."},
//     // {CommonError::ELCNotImplemented, "ELC není implementováno."},
//     // {CommonError::LicenceTypeNotImplemented, "Typ licence není implementován"}
//     };

enum class ELCType
{
  ELC1 = 1,
  ELC2 = 2,
  ELC3 = 3
};
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 Mapping
{
  std::map<string, LicenceType> licMapTypes = {{"EOV_OSV", LicenceType::EOS_EOV}, {"DDTS", LicenceType::DDTS}, {"DRT", LicenceType::DRT}};
  std::map<string, EncryptionType> licMapEncryption = {{"CID_AES256", EncryptionType::CID_AES256}, {"FIX_AES256", EncryptionType::FIX_AES256}};
  std::map<string, PlcType> licMapPlcType = {{"WAGO", PlcType::WAGO}, {"TECO", PlcType::TECO}};
};

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

struct LicenceIdentification
{
  ELCType licElcType = ELCType::ELC2;
  LicenceType licLicenceType;
  string licTypeName = "";
  PlcType licPlcType;

  uint8_t licenceVersion = 1; // verze licence, určitě kodování, pojmenování souborů
  uint8_t licenceIndex = 0;
  uint8_t revision;
  uint8_t licCompatibility = 1; // identikator hlavního ELC

  uint16_t licItemsCount = 0;
};

struct LicData
{
  string station = "";
  string distributor = "";
  string licenceName = "";
  string projectDescription = "";
  string cid = ""; // CID z SD karty
  string csd = ""; // CSD z SD karty
  string uid = ""; // jedinečný identifikátor z jiného systému
  pugi::xml_document *doc;
};

struct LicenceItem11
{
  int protocolId = -1;
  int dataPointsCount = 0;
};

struct LicenceItem21
{
  int protocolId = -1;
  int dataPointsCount = 0;
};

struct LicenceItem31
{
  int protocolId = -1;
  int dataPointsCount = 0;
};

struct LicenceInfo11
  {
    int reqDataPointsCount = 0;
    map<int, int> licences = {};
  };

 struct LicenceInfo21
  {
    int reqDataPointsCount = 0;
    map<int, int> licences = {};
  };

  struct LicenceInfo31
  {
    int reqDataPointsCount = 0;
    map<int, int> licences = {};
  };

  struct LicenceInfoGeneral
  {
    int reqDataPointsCount = 0;
    map<int, int> licences = {};
  };

class LicenceException : public std::exception
{
public:
  // Constructor with int and string parameters
  LicenceException(int errorCode, const std::string &errorMessage)
      : errorCode_(errorCode), errorMessage_(errorMessage) {}

  // Override the what() function to provide a description of the exception
  const char *what() const noexcept override
  {
    return errorMessage_.c_str();
  }

  // Getter functions for the exception members
  int getErrorCode() const
  {
    return errorCode_;
  }

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

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

#endif
