// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
#include "ANSLicense.h"
#include "Utility.h"

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

extern "C" __declspec(dllexport) int CreateANSLSHandle(ANSCENTER::ANSLSHelper * *Handle, const char* privateKey, const char* publicKey, const char* licenseServiceURL) {
    try {
        if (!Handle || !privateKey || !publicKey || !licenseServiceURL) return 0;
        std::string st_privateKey = privateKey;
        std::string st_publicKey = publicKey;
        std::string st_licenseServiceURL = licenseServiceURL;
        (*Handle) = new ANSCENTER::ANSLSHelper(st_privateKey, st_publicKey, st_licenseServiceURL);
        if (*Handle == nullptr) return 0;
        else return 1;
    }
	catch (...) {
		return 0;
	}
}
extern "C" __declspec(dllexport) int Release(ANSCENTER::ANSLSHelper * *Handle) {
    try {
        if (!Handle || !(*Handle)) return 1; // already released
        delete* Handle;
        *Handle = nullptr;
        return 1;
    }
	catch (...) {
		return 0;
	}
}
extern "C" __declspec(dllexport) void SetLicenseServiceURL(ANSCENTER::ANSLSHelper * *Handle, const char* licenseServiceURL) {
    if (!Handle || !(*Handle) || !licenseServiceURL) return;
    (*Handle)->SetLicenseServiceURL(licenseServiceURL);
}
extern "C" __declspec(dllexport) int GetLicenseData(ANSCENTER::ANSLSHelper * *Handle, const char* licenseKey, LStrHandle licenseData) {
    try {
        if (!Handle || !(*Handle) || !licenseKey) return 0;
        std::string st = (*Handle)->GetLicenseData(licenseKey);
        int size = (int)st.length();
        if (size > 0) {
            MgErr error;
            error = DSSetHandleSize(licenseData, sizeof(int32) + size * sizeof(uChar));
            if (error == noErr)
            {
                (*licenseData)->cnt = size;
                memcpy((*licenseData)->str, st.c_str(), size);
                return 1;
            }
            else return 0;
        }
        else {
            return 0;
        }
    }
	catch (...) {
		return 0;
	}
}
extern "C" __declspec(dllexport) int LoadLicenseTemplate(ANSCENTER::ANSLSHelper * *Handle, const char* templateFilePath) {
    try {
        if (!Handle || !(*Handle) || !templateFilePath) return 0;
        bool result = (*Handle)->LoadLicenseTemplate(templateFilePath);
        if (result == true) return 1;
        else return 0;
    }
	catch (...) {
		return 0;
	}
}
extern "C" __declspec(dllexport) int GetCurrentHardwareId(ANSCENTER::ANSLSHelper * *Handle, LStrHandle currentHwID) {
    try {
        if (!Handle || !(*Handle)) return 0;
        std::string st = (*Handle)->GetCurrentHardwareId();
        int size = (int)st.length();
        if (size > 0) {
            MgErr error;
            error = DSSetHandleSize(currentHwID, sizeof(int32) + size * sizeof(uChar));
            if (error == noErr)
            {
                (*currentHwID)->cnt = size;
                memcpy((*currentHwID)->str, st.c_str(), size);
                return 1;
            }
            else return 0;
        }
        else return 0;
    }
	catch (...) {
		return 0;
	}
}
extern "C" __declspec(dllexport) int GenerateKey(ANSCENTER::ANSLSHelper * *Handle, int productId, const char* registrationName, int productFeature, int trialLicense, LStrHandle generatedKey) {
    try {
        if (!Handle || !(*Handle) || !registrationName) return 0;
        bool enableTrialLicense = false;
        if (trialLicense > 0)enableTrialLicense = true;
        std::string st = (*Handle)->GenerateKey(productId, registrationName, productFeature, enableTrialLicense);
        int size = (int)st.length();
        if (size > 0) {
            MgErr error;
            error = DSSetHandleSize(generatedKey, sizeof(int32) + size * sizeof(uChar));
            if (error == noErr)
            {
                (*generatedKey)->cnt = size;
                memcpy((*generatedKey)->str, st.c_str(), size);
                return 1;
            }
            else return 0;
        }
        else return 0;
    }
    catch (...) {
        return 0;
    }
}

extern "C" __declspec(dllexport) int GenerateKeyWithExpiredDate(ANSCENTER::ANSLSHelper * *Handle, int productId, const char* registrationName, int productFeature, int expiredYear, int expiredMonth, int expiredDate, LStrHandle generatedKey) {
    try {
        if (!Handle || !(*Handle) || !registrationName) return 0;
        std::string st = (*Handle)->GenerateKey(productId, registrationName, productFeature, expiredYear, expiredMonth, expiredDate);
        int size = (int)st.length();
        if (size > 0) {
            MgErr error;
            error = DSSetHandleSize(generatedKey, sizeof(int32) + size * sizeof(uChar));
            if (error == noErr)
            {
                (*generatedKey)->cnt = size;
                memcpy((*generatedKey)->str, st.c_str(), size);
                return 1;
            }
            else return 0;
        }
        else return 0;
    }
	catch (...) {
		return 0;
	}

}

extern "C" __declspec(dllexport)  int CheckLicenseKey(ANSCENTER::ANSLSHelper * *Handle, const char* licenseKey, const char* registrationName, int productId){ //, LStrHandle strEnableFeature) {   // Check if the license key is valid
    try {
        if (!Handle || !(*Handle) || !licenseKey || !registrationName) return -1;
        int enFeatures = 0;
        bool result = (*Handle)->CheckLicenseKey(licenseKey, registrationName, productId, enFeatures);
        if (result) return enFeatures;
        else return -1;
    }
    catch (...) {
        return -1;
    }
}
extern "C" __declspec(dllexport) int ValidateLicense(ANSCENTER::ANSLSHelper * *Handle, const char* licenseKey, const char* registrationName, const char* existingActivationKey,LStrHandle activationKey) {
    try {
        if (!Handle || !(*Handle) || !licenseKey || !registrationName || !existingActivationKey) return UNKNOWN;
        std::string st = existingActivationKey;
        int result = (*Handle)->ValidateLicense(licenseKey, registrationName, st);
        int size = (int)st.length();
        if (size > 0) {
            MgErr error;
            error = DSSetHandleSize(activationKey, sizeof(int32) + size * sizeof(uChar));
            if (error == noErr)
            {
                (*activationKey)->cnt = size;
                memcpy((*activationKey)->str, st.c_str(), size);
                return result;
            }
            else return UNKNOWN;
        }
        else return INVALID_LICENSE_KEY;
    }
    catch (...) {
        return UNKNOWN;
    }

}
extern "C" __declspec(dllexport) int ActivateLicense(ANSCENTER::ANSLSHelper * *Handle, const char* licenseKey, const char* registrationName, LStrHandle activationKey) { // Always activate the license (need internet connection)
    try {
        if (!Handle || !(*Handle) || !licenseKey || !registrationName) return UNKNOWN;
        std::string st = "";
        int result = (*Handle)->ActivateLicense(licenseKey, registrationName, st);
        int size = (int)st.length();
        if (size > 0) {
            MgErr error;
            error = DSSetHandleSize(activationKey, sizeof(int32) + size * sizeof(uChar));
            if (error == noErr)
            {
                (*activationKey)->cnt = size;
                memcpy((*activationKey)->str, st.c_str(), size);
                return result;
            }
            else return UNKNOWN;
        }
        else return INVALID_LICENSE_KEY;
    }
	catch (...) {
		return UNKNOWN;
	}
}

extern "C" __declspec(dllexport) int ActivateLicenseWithCustomHWID(ANSCENTER::ANSLSHelper * *Handle, const char* licenseKey, const char* registrationName, const char* hardwareId, LStrHandle activationKey) {
    try {
        if (!Handle || !(*Handle) || !licenseKey || !registrationName || !hardwareId) return UNKNOWN;
        std::string st;
        int result = (*Handle)->ActivateLicenseWithCustomHWID(licenseKey, registrationName, hardwareId, st);
        int size = (int)st.length();
        if (size > 0) {
            MgErr error;
            error = DSSetHandleSize(activationKey, sizeof(int32) + size * sizeof(uChar));
            if (error == noErr)
            {
                (*activationKey)->cnt = size;
                memcpy((*activationKey)->str, st.c_str(), size);
                return result;
            }
            else return UNKNOWN;
        }
        else return INVALID_LICENSE_KEY;
    }
	catch (...) {
		return UNKNOWN;
	}
}// Always activate the license (need internet connection)

extern "C" __declspec(dllexport) int IsLicenseKeyValid(ANSCENTER::ANSLSHelper **Handle, const char* licenseKey, const char * registrationName) { // Only check the license key with registration name and expiration date only. This is used when developer to use internal APIs called
    try {
        if (!Handle || !(*Handle) || !licenseKey || !registrationName) return 0;
        bool result = (*Handle)->IsLicenseKeyValid(licenseKey, registrationName);
        if (result) return 1;
        else return 0;
    }
	catch (...) {
		return 0;
	}
}


extern "C" __declspec(dllexport) int GenerateOfflineActivationData(ANSCENTER::ANSLSHelper * *Handle, const char* licenseKey, const char* registrationName, LStrHandle offlineActivationData) {
    try {
        if (!Handle || !(*Handle) || !licenseKey || !registrationName) return 0;
        std::string st = "";
        int result = (*Handle)->GenerateOfflineActivationData(licenseKey, registrationName, st);
        int size = (int)st.length();
        if (size > 0) {
            MgErr error;
            error = DSSetHandleSize(offlineActivationData, sizeof(int32) + size * sizeof(uChar));
            if (error == noErr)
            {
                (*offlineActivationData)->cnt = size;
                memcpy((*offlineActivationData)->str, st.c_str(), size);
                return 1;
            }
            else return 0;
        }
        else return 0;
    }
	catch (...) {
		return 0;
	}
}

extern "C" __declspec(dllexport) int InstallOfflineLicense(ANSCENTER::ANSLSHelper * *Handle, const char* licenseKey, const char* registrationName, const char* activationKey) {
    try {
        if (!Handle || !(*Handle) || !licenseKey || !registrationName || !activationKey) return 0;
        return (*Handle)->InstallOfflineLicense(licenseKey, registrationName, activationKey);
    }
    catch (...) {
        return 0;
    }
}


//Utilities
extern "C" __declspec(dllexport) int ExtractModelZipFile(const char* modelZipFile, const char* password, const char* modelName, LStrHandle extractedOutputFolder) {
    try {
        std::string st = "";
        int result = ANSCENTER::ANSLSHelper::ExtractModelZipFile(modelZipFile, password, modelName, st);
        int size = (int)st.length();
        if (size > 0) {
            MgErr error;
            error = DSSetHandleSize(extractedOutputFolder, sizeof(int32) + size * sizeof(uChar));
            if (error == noErr)
            {
                (*extractedOutputFolder)->cnt = size;
                memcpy((*extractedOutputFolder)->str, st.c_str(), size);
                return 1;
            }
        }
        return result;
    }
	catch (...) {
		return 0;
	}
}

extern "C" __declspec(dllexport) int ZipFolderToZipFile(const char* modelFolderSource, const char* modelZipFileDes, const char* password) {
    try {
        std::string stPass = password;
        if (stPass.empty()) password = "Sh7O7nUe7vJ/417W0gWX+dSdfcP9hUqtf/fEqJGqxYL3PedvHubJag==";
        bool result = ANSCENTER::ANSLSHelper::ZipFolerWithPassword(modelFolderSource, modelZipFileDes, password);
        if (result == true) return 1;
        else return 0;
    }
	catch (...) {
		return 0;
	}
}

extern "C" __declspec(dllexport) int PrepareEdgeModel(const char* modelZipFile, const char* zipFilePassword, const char* edgePassword, const char* modelName, const char* edgeSerialNumber,LStrHandle pathArray) {
    try {
        std::string st_configFilePathName = "";
        std::string st_labelMapPathName = "";
        std::string st_zipFilePathName = "";
        int result = ANSCENTER::ANSLSHelper::PrepareEdgeModel(modelZipFile, zipFilePassword, edgePassword, modelName, edgeSerialNumber, st_configFilePathName, st_labelMapPathName, st_zipFilePathName);
        std::string st = st_configFilePathName + ";" + st_labelMapPathName + ";" + st_zipFilePathName;
        int size = (int)st.length();
        if (size > 0) {
            MgErr error;
            error = DSSetHandleSize(pathArray, sizeof(int32) + size * sizeof(uChar));
            if (error == noErr)
            {
                (*pathArray)->cnt = size;
                memcpy((*pathArray)->str, st.c_str(), size);
                return 1;
            }
        }
        return result;
    }
	catch (...) {
		return 0;
	}
}

extern "C" __declspec(dllexport) int GetSystemHardwareInformation(LStrHandle systemHardwareInformation) {
    try {
        std::string st = ANSCENTER::ANSLSHelper::GetSystemHardwareInformation();
        int size = (int)st.length();
        if (size > 0) {
            MgErr error;
            error = DSSetHandleSize(systemHardwareInformation, sizeof(int32) + size * sizeof(uChar));
            if (error == noErr)
            {
                (*systemHardwareInformation)->cnt = size;
                memcpy((*systemHardwareInformation)->str, st.c_str(), size);
                return 1;
            }
            else return 0;
        }
        else return 0;
    }
	catch (...) {
		return 0;
	}
}

extern "C" __declspec(dllexport) int ReleaseLoggers() {
    try {
        bool result = ANSCENTER::ANSLSHelper::ReleaseLogger();
        if (result) return 1;
        else return 0;
    }
	catch (...) {
		return 0;
	}
}

extern "C" __declspec(dllexport) int ListANSLicenses(std::string & listLicense) {
    try {
        listLicense = ANSCENTER::ANSLicenseHelper::ListLicenses();
        if (!listLicense.empty()) return 1;
        else return 0;
    }
	catch (...) {
		return 0;
	}
}


extern "C" __declspec(dllexport) int ListANSLicenses_LV(LStrHandle ansProductLicenses) {
    try {
        std::string st = ANSCENTER::ANSLicenseHelper::ListLicenses();
        int size = (int)st.length();
        if (size > 0) {
            MgErr error;
            error = DSSetHandleSize(ansProductLicenses, sizeof(int32) + size * sizeof(uChar));
            if (error == noErr)
            {
                (*ansProductLicenses)->cnt = size;
                memcpy((*ansProductLicenses)->str, st.c_str(), size);
                return 1;
            }
            else return 0;
        }
        else return 0;
    }
	catch (...) {
		return 0;
	}
}
extern "C" __declspec(dllexport) int ActivateTrialLicense(const char* productName) {
    return ANSCENTER::ANSLicenseHelper::ActivateTrialLicense(productName);
}
extern "C" __declspec(dllexport) int DeactivateLicense(const char* productName) {
    return ANSCENTER::ANSLicenseHelper::DeactivateLicense(productName);
}

extern "C" __declspec(dllexport) int ActivateProductLicense(const char* productName, const char* licenseKey) {
    return ANSCENTER::ANSLicenseHelper::ActivateLicense(productName,licenseKey);
}
extern "C" __declspec(dllexport) int ActivateProductLicenseWithCustomHWID(const char* productName, const char* licenseKey, const char* hwid, LStrHandle lvActivationKey) {
    try {
        std::string st;
        int result = ANSCENTER::ANSLicenseHelper::ActivateLicenseWithCustomHWID(productName, licenseKey, hwid, st);

        int size = (int)st.length();
        if (size > 0) {
            MgErr error;
            error = DSSetHandleSize(lvActivationKey, sizeof(int32) + size * sizeof(uChar));
            if (error == noErr)
            {
                (*lvActivationKey)->cnt = size;
                memcpy((*lvActivationKey)->str, st.c_str(), size);
                return result;
            }
            else return LicenseKeyStatus::UNKNOWN;
        }
        else return  LicenseKeyStatus::INVALID_LICENSE_KEY;
    }
	catch (...) {
		return LicenseKeyStatus::UNKNOWN;
	}
}

extern "C" __declspec(dllexport) int GetRegistrationName(const char* validationData, LStrHandle registrationName) {
    try {
        std::string st = ANSCENTER::ANSLicenseHelper::DecodeValidationData(validationData);
        int size = (int)st.length();
        if (size > 0) {
            MgErr error;
            error = DSSetHandleSize(registrationName, sizeof(int32) + size * sizeof(uChar));
            if (error == noErr)
            {
                (*registrationName)->cnt = size;
                memcpy((*registrationName)->str, st.c_str(), size);
                return 1;
            }
            else return 0;
        }
        else return  0;
    }
	catch (...) {
		return 0;
	}
}


extern "C" __declspec(dllexport) int GenerateActivationKeyData(const char* activationKey, const char* licenseKey, const char* hardwareId, const char* validationData, LStrHandle activationData) {
    try {
        std::string st = ANSCENTER::ANSLicenseHelper::GenerateActivationDataFile(activationKey, licenseKey, hardwareId, validationData);
        int size = (int)st.length();
        if (size > 0) {
            MgErr error;
            error = DSSetHandleSize(activationData, sizeof(int32) + size * sizeof(uChar));
            if (error == noErr)
            {
                (*activationData)->cnt = size;
                memcpy((*activationData)->str, st.c_str(), size);
                return 1;
            }
            else return 0;
        }
        else return  0;
    }
    catch (...) {
        return 0;
    }
}

extern "C" __declspec(dllexport) int ANSLicenseVerification(const char* licenseKey, int productId, const char* registrationName) {
    try{
        bool result = ANSCENTER::ANSLicenseHelper::LicenseVerification(licenseKey, productId, registrationName);
        if (result)return 1;
        else return 0;
    }
    catch (...) {
        return 0;
    }
}


extern "C" __declspec(dllexport) int ANSModelConversion(const char* zipModelFile, const char* zipModelPassword) {
    try {
        //1. Uzip the model file to a temp location
        std::string parentFolder = GetParentFolder(zipModelFile);
        if (parentFolder.empty()) {
            return -1; // or handle error appropriately
        }
        std::string modelName = GetFileNameWithoutExtension(zipModelFile) + "_converted";
        const std::string outputFolder = GenerateOutputFolder(zipModelFile, modelName, true);
        if (!FolderExist(outputFolder)) fs::create_directory(outputFolder);
        bool extractedResult = ExtractProtectedZipFile(zipModelFile, zipModelPassword, modelName, outputFolder);
        if (!extractedResult) return 0;
        //2. Zip the model file to a temp location
        std::string newModelZipFile = CreateFilePath(parentFolder, modelName + ".zip");
        std::string newModelZipPassword = "Sh7O7nUe7vJ/417W0gWX+dSdfcP9hUqtf/fEqJGqxYL3PedvHubJag==";
        //3. Read names of classes from the label map file
        std::string labelMapFile = CreateFilePath(outputFolder, "classes.names");
        if (labelMapFile.empty()) return 0;
        std::vector<std::string> classesNames = Split(ReadFileContent(labelMapFile), "\n");
        // 4. Create Categories folder
        std::string categoriesFolder = outputFolder + "\\Categories";
        if (FolderExist(categoriesFolder))DeleteFolder(categoriesFolder);
        fs::create_directory(categoriesFolder);
        for (size_t i = 0; i < classesNames.size(); ++i) {
            std::ofstream outFile(categoriesFolder + "/" + classesNames[i] + "." + std::to_string(i + 1));
            outFile.close();
        }
        bool zipResult = ZipFolderWithPassword(outputFolder.c_str(), newModelZipFile.c_str(), newModelZipPassword.c_str());
        if (zipResult) {
            DeleteFolder(outputFolder);
            return 1;
        }
        else return 0;
    }
	catch (...) {
		return 0;
	}
}
extern "C" __declspec(dllexport) int DeletePathRecursively(const char* pathTobeDeleted) {
    try {
        bool result = ANSCENTER::ANSLicenseHelper::DeleleteRecursively(pathTobeDeleted);
        if (result) return 1;
        else return 0;
    }
    catch (...) {
        return 0;
	}
}
