#include <licenceReader.h>
#ifndef EZ_APPLICATION_LICENCE_DISABLE

ELCType licElcType = ELCType::ELC2;
LicenceType licLicenceType;
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

LicenceReader::LicenceReader()
{
}

/// @brief provede pouze inicialazaci čtecí třídy
/// @param elcType
/// @param initStructure
/// @return
bool LicenceReader::init(int elcType, InitStructure &initStructure)
{
  try
  {
    if (elcType > 3)
    {
      error.code = (int)GeneralError::ELCNotImplemented;
      error.message = "ELC není implementováno.";
      throw LicenceException((int)GeneralError::ELCNotImplemented, error.message);
    }

    this->licIdentification.licElcType = (ELCType)elcType;
    this->licIdentification.licLicenceType = (LicenceType)initStructure.licenceType;
    this->licIdentification.licenceVersion = licenceVersion;
    this->licIdentification.licenceIndex = licenceIndex;
    this->licIdentification.licCompatibility = initStructure.compatibility;
  }
  catch (const LicenceException &ex)
  {
    error.code = ex.getErrorCode();
    error.message = ex.getErrorMessage();
    return false;
  }

  elcSwitchType = elcType * 10 + licCompatibility;

  return true;
}

/// @brief provede inicializaci čtecí třídy a zároveň načte licenční body do obecné struktury
/// @param elcType
/// @param licenceType
/// @param licenceVersion
/// @param licenceIndex
/// @param compatibility
/// @return
bool LicenceReader::initread(int elcType, InitStructure &initStructure)
{
  try
  {
    elcSwitchType = elcType * 10 + initStructure.compatibility;

    if (init(elcType, initStructure))
    {
      switch (this->licIdentification.licElcType)
      {
      case ELCType::ELC1:
      { 
        Reader::Licence1 licenceELC1 = Reader::Licence1(this->licIdentification);
        this->licence1 = &licenceELC1;
        licenceELC1.cid_cdsPath = initStructure.cid_csd_filePath;
        licenceELC1.licenceFilePath = initStructure.licenceFilePath;

        try
        {
          this->licence1->readLicence(&this->licencesInfo);
        }
        catch (const LicenceException &ex)
        {
          error.code = ex.getErrorCode();
          error.message = ex.getErrorMessage();
          return false;
        }
        break;
      }
      case ELCType::ELC2:
      {
        Reader::Licence2 licenceELC2 = Reader::Licence2(this->licIdentification);
        this->licence2 = &licenceELC2;
        licenceELC2.cid_cdsPath = initStructure.cid_csd_filePath;
        licenceELC2.licenceFilePath = initStructure.licenceFilePath;
        this->licence2->readLicence(&this->licencesInfo);
        
        this->sdCardInfo.isLoaded = true;
        this->sdCardInfo.serialNumber = this->licence2->sdCard.cardData.serialNumber;
        this->sdCardInfo.cardSize = this->licence2->sdCard.cardData.cardSize;
        this->sdCardInfo.date = this->licence2->sdCard.cardData.date;
        this->sdCardInfo.name = this->licence2->sdCard.cardData.name;
        this->sdCardInfo.oemID = this->licence2->sdCard.cardData.oemID;

        this->licInfo.licenceFileName = this->licence2->licFileName;
        this->licInfo.licenceFilePath = this->licence2->licenceFilePath; 

        //this->licenceInfo.
        //this->sdCardInfo.licenceFileName = this->licence2->licFileName;

        break;
      }
      case ELCType::ELC3:
      {
        Reader::Licence3 licenceELC3 = Reader::Licence3(this->licIdentification);
        this->licence3 = &licenceELC3;
        this->licence3->uid_path = initStructure.uid_filePath;
        licenceELC3.licenceFilePath = initStructure.licenceFilePath;
        this->licence3->readLicence(&this->licencesInfo);
        this->licInfo.licenceFileName = this->licence3->licFileName;
        break;
      }
      default:
        throw LicenceException((int)GeneralError::ELCNotImplemented, "Toto ELC není implementováno");
      }
    }
    else
      return false;
  }
  catch (const LicenceException &ex)
  {
    error.code = ex.getErrorCode();
    error.message = ex.getErrorMessage();
    return false;
  }

  return true; // TODO testy
}

/// @brief vrací informace o licenčím bodu na základě id protocolu a předané návratové struktury
/// vrací false při chybě nebo v případě, ze pro daný protokol není dostatečný počet licenčních bodů
/// @param protocolId
/// @param returnItemStructure
/// @return
bool LicenceReader::getLicenceItemInfo(int protocolId, void *returnItemStructure)
{
  try
  {
    switch (this->licIdentification.licElcType)
    {
    case ELCType::ELC1:
    {
      if (!this->licIdentification.licCompatibility) // defaultní kompatibilita
      {
        LicenceELC1Info *resultPtr = static_cast<LicenceELC1Info *>(returnItemStructure);
        if (this->licencesInfo.licences.count(1)) // stare eov má natvrdo "id" 1.
          resultPtr->isValid = true;
        else
          resultPtr->isValid = false;
      }
      else
      {
        LicenceException((int)GeneralError::CompatibilityTypeNotImplemented, "Kompatibilita není implementována.");
      }
      break;
    }
    case ELCType::ELC2:
    {
      if (!this->licIdentification.licCompatibility || licIdentification.licCompatibility == 1) // defaultní kompatibilita
      {
        LicenceELC2Item *resultPtr = static_cast<LicenceELC2Item *>(returnItemStructure);
        resultPtr->protocolId = protocolId;
        if (this->licencesInfo.licences.count(protocolId))
          resultPtr->dataPointsCount = this->licencesInfo.licences.at(protocolId);
        else
        {
          resultPtr->dataPointsCount = 0;
          error.code = 0;
          error.message = "Protokol: " + to_string(protocolId) + " nemá licenční body";
          return false;
        }
      }
      else
      {
        switch (this->licIdentification.licCompatibility)
        {
        case 1:
        {
          // kod pro kompatibilitu 1
          break;
        }
        default:
          LicenceException((int)GeneralError::CompatibilityTypeNotImplemented, "Kompatibilita není implementována.");
          break;
        }
      }
      break;
    }
    case ELCType::ELC3:
    {
      cout << "komp: " << this->licIdentification.licCompatibility << "\n";
      if (!this->licIdentification.licCompatibility || licIdentification.licCompatibility == 1) // defaultní kompatibilita
      {
        LicenceELC3Item *resultPtr = static_cast<LicenceELC3Item *>(returnItemStructure);
        resultPtr->protocolId = protocolId;
        if (this->licencesInfo.licences.count(protocolId))
          resultPtr->dataPointsCount = this->licencesInfo.licences.at(protocolId);
        else
        {
          resultPtr->dataPointsCount = 0;
          error.code = 0;
          error.message = "Protokol: " + to_string(protocolId) + " nemá licenční body";
          return false;
        }
      }
      else
      {
        switch (this->licIdentification.licCompatibility)
        {
        case 1:
        {
          // kod pro kompatibilitu 1
          break;
        }
        default:
          LicenceException((int)GeneralError::CompatibilityTypeNotImplemented, "Kompatibilita není implementována.");
          break;
        }
      }
      break;
    }
    default:
    {
      error.code = -1;
      error.message = "Nepodařilo se identifikovat licenci";
      return false;
    }
    }
  }
  catch (const LicenceException &ex)
  {
    error.code = ex.getErrorCode();
    error.message = ex.getErrorMessage();
    return false;
  }

  return true;
}

/// @brief vrací informace o všech licenčních bodech základě předané návratové struktury
/// @param returnStructure
/// @return
bool LicenceReader::getLicenceInfo(void *returnStructure)
{
  try
  {
    switch (this->licIdentification.licElcType)
    {
    case ELCType::ELC1:
    {                                                // old eoseov
      if (!this->licIdentification.licCompatibility) // defaultní kompatibilita
      {
        LicenceELC1Info *resultPtr = static_cast<LicenceELC1Info *>(returnStructure);

        if (this->licencesInfo.licences.count(1)) // starý EOS má natvrdo "id" 1
        {
          resultPtr->isValid = true;
        }
        else
        {
          resultPtr->isValid = false;
        }
      }
      else
      {
        switch (this->licIdentification.licCompatibility)
        {
        case 1:
          // kod pro kompatibilitu 1
          break;
        default:
          LicenceException((int)GeneralError::CompatibilityTypeNotImplemented, "Kompatibilita není implementována.");
          break;
        }
      }
      break;
    }
    case ELCType::ELC2:
    {
      if (!this->licIdentification.licCompatibility) // defaultní kompatibilita
      {
        Reader::Licence2 licenceELC2 = Reader::Licence2(this->licIdentification);
        licenceELC2.readLicence(&this->licencesInfo);
        licenceELC2.getLicenceInfo(returnStructure);
      }
      else
      {
        switch (this->licIdentification.licCompatibility)
        {
        case 1:
          // kod pro kompatibilitu 1
          break;
        default:
          LicenceException((int)GeneralError::CompatibilityTypeNotImplemented, "Kompatibilita není implementována.");
          break;
        }
      }
      break;
    }
    case ELCType::ELC3:
    {
      break;
    }
    }
  }
  catch (const LicenceException &ex)
  {
    error.code = ex.getErrorCode();
    error.message = ex.getErrorMessage();
    return false;
  }
  return true;
}

LicenceReader::~LicenceReader()
{
}

#endif