#include <stdio.h>
#include <filesystem>
#include <cstdlib>
#include <licenceGenerator.h>
#include "utils.h"
#include "pugixml.hpp"
#include <typeinfo>

LicenceGenerator::LicenceGenerator()
{
}

LicenceGenerator::LicenceGenerator(string uid, string cid, string csd, string dataFileName)
{

  if (dataFileName.empty())
    throw LicenceException((int)GeneralError::ParamMissing, "Missing par: dataFileName");

  if (uid.empty() == false)
  {
    if (uid.length() < 32) throw LicenceException((int)GeneralError::IvanlidParam, "UID incorrect size");
    this->licData.uid = uid;
  }
  else
  {
    if (cid.empty())
      throw LicenceException((int)GeneralError::ParamMissing, "Missing par: CID");
    if (csd.empty())
      throw LicenceException((int)GeneralError::ParamMissing, "Missing par: CSD");
  }

  this->configFileName = dataFileName;
  this->licData.cid = cid;
  this->licData.csd = csd;

  this->argumentsCorrect = true;

  processInputConfiguration();
}

bool LicenceGenerator::processInputConfiguration()
{

  string fullFile = getCompletePath(this->configFileName);
    const int fileNameLength = fullFile.length();
  char fileName[fileNameLength] = {};
  getCharsFromString(fullFile, fileName, fileNameLength);

#ifdef EZ_LIC_DEBUG
  pugi::xml_parse_result result = doc.load_file("licData.xml");
#else
  pugi::xml_parse_result result = doc.load_file(fileName);
#endif
  if (result)
  {
    const char *dataRootName = doc.child("data") ? "data" : "licence"; // kompatibilita s verzí, která měla ještě root "data"

    if (atoi(&doc.child(dataRootName).attribute("xmlVersion").value()[0]) != XML_VERSION)
    {
      throw LicenceException((int)GeneralError::IvanlidParam, "Invalid param: XML VERSION");
    }

    this->licData.doc = &doc;

    string licType = doc.child(dataRootName).child("licenceType").child_value();
    if (!licType.empty())
    {
      this->licIdentification.licLicenceType = mapping.licMapTypes[licType]; // LicenceType::EOS_EOV;
    }
    else
    {
      throw LicenceException((int)GeneralError::ParamMissing, "ERROR MISSING licenceType");
    }

    this->licIdentification.licenceVersion = atoi(&doc.child(dataRootName).child("licenceType").attribute("licenceVersion").value()[0]);
    this->licIdentification.revision = doc.child(dataRootName).attribute("revision").value()[0];
    this->licIdentification.licenceIndex = atoi(&doc.child(dataRootName).child("licenceType").attribute("licenceIndex").value()[0]);
    this->licIdentification.licElcType = (ELCType)atoi(&doc.child(dataRootName).attribute("elc").value()[0]);

    this->licIdentification.licCompatibility = atoi(&doc.child(dataRootName).attribute("compatibility").value()[0]);

    string plcType = doc.child(dataRootName).child("plcType").child_value();
    if (!plcType.empty())
    {
      this->licIdentification.licPlcType = mapping.licMapPlcType[plcType];
    }
  }
  else
  {
    throw LicenceException((int)GeneralError::FileOpenError, "Unable to open the config file: " + fullFile + "\n");
  }
  return true;
}

void LicenceGenerator::createLicenceFile()
{
  switch (this->licIdentification.licElcType)
  {
  case ELCType::ELC1:
    createLicenceELC1();
    break;

  case ELCType::ELC2:
    createLicenceELC2();
    break;

  case ELCType::ELC3:
    createLicenceELC3();
    break;
  }
}

void LicenceGenerator::createLicenceELC1() // přejmenvat na ELC1
{
  Generator::Licence1 licence = Generator::Licence1(this->licData.cid, this->licData.csd, this->configFileName);
  licence.createLicence();
}

void LicenceGenerator::createLicenceELC2()
{
  switch (this->licIdentification.licCompatibility)
  {
  case 1:
  {
    Generator::Licence2 licence = Generator::Licence2(licData.cid, licData.csd, licData.doc);
    licence.createLicence();
    break;
  }
  default:
    throw LicenceException((int)GeneralError::CompatibilityTypeNotImplemented, "Compatibility not implemented.");
  }
}

void LicenceGenerator::createLicenceELC3()
{
  switch (this->licIdentification.licCompatibility)
  {
  case 1:
  {
    Generator::Licence3 licence = Generator::Licence3(licData.uid, licData.doc);
    licence.createLicence();
    break;
  }
  default:
    throw LicenceException((int)GeneralError::CompatibilityTypeNotImplemented, "Compatibility not implemented.");
  }
}

LicenceGenerator::~LicenceGenerator()
{
}
