﻿using System;
using UnityEngine;
using LicenseSpring;

namespace LicenseSpring
{
    public class LicenseSpringSDK : MonoBehaviour
    {
        #region Declaration

        [HideInInspector]
        LicenseSpringSDKObject sdkObject;

        [HideInInspector]
        public ExtendedOptions extendedOptions;

        [HideInInspector]
        public Configuration licenseConfiguration;

        [HideInInspector]
        public ProductDetails productDetails;

        [HideInInspector]
        public ILicense license;

        [HideInInspector]
        public InstallationFile installationFile;

        private ILicenseManager licenseManager;

        /// <summary>
        /// Check sdk exception
        /// </summary>
        public static event Action<Exception> sdkException;

        #endregion

        #region SDK methods

        public void InitializeSDK()
        {
            try
            {
                sdkObject = this.gameObject.GetComponent<LicenseSpringSDKObject>();

                extendedOptions = new ExtendedOptions();

                extendedOptions.LicenseFilePath = Application.persistentDataPath + "/License.Key";
                extendedOptions.HardwareID = SystemInfo.deviceUniqueIdentifier;

                if (Debug.isDebugBuild)
                {
                    extendedOptions.EnableLogging = true;
                }
                else
                {
                    extendedOptions.EnableLogging = false;
                }

                extendedOptions.CollectNetworkInfo = true;

                licenseConfiguration = new Configuration(
                apiKey: sdkObject.ApiKey,
                sharedKey: sdkObject.SharedKey,
                productCode: sdkObject.ProductCode,
                appName: sdkObject.AppName,
                appVersion: sdkObject.AppVersion,
                extendedOptions: extendedOptions);

                licenseConfiguration.OSVersion = SystemInfo.operatingSystem;

                licenseManager = LicenseManager.GetInstance();
                licenseManager.Initialize(licenseConfiguration);

                productDetails = licenseManager.GetProductDetails();

                license = licenseManager.CurrentLicense();
                
                Debug.Log("Initialization succeeded!");
            }
            catch (System.Exception ex)
            {
                sdkException?.Invoke(ex);
            }

            
        }

        public void InitializeSDK(string licenseKey)
        {
            try
            {
                InitializeSDK();
                ActivateLicense(licenseKey);
            }
            catch (System.Exception ex)
            {
                sdkException?.Invoke(ex);
            }
        }

        #region License data

        public string GetTrialLicense()
        {
            try
            {
                return licenseManager.GetTrialLicense();
            }
            catch (System.Exception ex)
            {
                sdkException?.Invoke(ex);
                return null;
            }
        }

        public ILicense ActivateLicense(string licenseKey)
        {
            LicenseSpring.LicenseID key = LicenseID.FromKey(licenseKey);

            try
            {
                if (licenseKey != null && licenseKey != "")
                {
                    license = licenseManager.ActivateLicense(key);
                }
                return license;
            }
            catch (System.Exception ex)
            {
                sdkException?.Invoke(ex);
                return null;
            }
        }

        public ILicense ActivateLicense(string user, string password)
        {
            LicenseSpring.LicenseID data = LicenseID.FromUser(user, password);

            try
            {
                license = licenseManager.ActivateLicense(data);
                return license;
            }
            catch (System.Exception ex)
            {
                sdkException?.Invoke(ex);
                return null;
            }
        }

        public ILicense ActivateLicenseOffline(string activationResponseFile)
        {
            try
            {
                license = licenseManager.ActivateLicenseOffline(activationResponseFile);
                return license;
            }
            catch (System.Exception ex)
            {
                sdkException?.Invoke(ex);
                return null;
            }
        }

        public bool ChangePassword(string user, string password, string newPassword)
        {
            LicenseSpring.LicenseID data = LicenseID.FromUser(user, password);

            try
            {
                return licenseManager.ChangePassword(data, newPassword);
            }
            catch (System.Exception ex)
            {
                sdkException?.Invoke(ex);
                return false;
            }
        }

        public void ChangePassword()
        {
            try
            {
                licenseManager.ClearLocalStorage();
            }
            catch (System.Exception ex)
            {
                sdkException?.Invoke(ex);
            }
        }

        public void ClearLocalStorage()
        {
            try
            {
                licenseManager.ClearLocalStorage();
            }
            catch (System.Exception ex)
            {
                sdkException?.Invoke(ex);
            }
        }

        public string[] GetAllVersions(string licenseKey)
        {
            LicenseSpring.LicenseID key = LicenseID.FromKey(licenseKey);
            try
            {
                return licenseManager.GetAllVersions(key);
            }
            catch (System.Exception ex)
            {
                sdkException?.Invoke(ex);
                return null;
            }
        }

        public string[] GetAllVersionsByUser(string user)
        {
            LicenseSpring.LicenseID data = LicenseID.FromUser(user);

            try
            {
                return licenseManager.GetAllVersions(data);
            }
            catch (System.Exception ex)
            {
                sdkException?.Invoke(ex);
                return null;
            }
        }

        public InstallationFile GetInstallationFile(string licenseKey, string version = null)
        {
            LicenseSpring.LicenseID key = LicenseID.FromKey(licenseKey);

            try
            {
                return licenseManager.GetInstallationFile(key, version);
            }
            catch (System.Exception ex)
            {
                sdkException?.Invoke(ex);
                return null;
            }
        }

        public InstallationFile GetInstallationFileByUser(string user, string version = null)
        {
            LicenseSpring.LicenseID data = LicenseID.FromUser(user);

            try
            {
                return licenseManager.GetInstallationFile(data, version);
            }
            catch (System.Exception ex)
            {
                sdkException?.Invoke(ex);
                return null;
            }
        }

        public string CheckLicense(string licenseKey = null)
        {
            try
            {
                if (licenseKey == null || licenseKey == "")
                {
                    return InstallationFileToString(license.Check());
                }
                else
                {
                    LicenseSpring.LicenseID key = LicenseID.FromKey(licenseKey);

                    return InstallationFileToString(licenseManager.ActivateLicense(key).Check());
                }
            }
            catch (System.Exception ex)
            {
                sdkException?.Invoke(ex);
                return null;
            }
        }

        /// <summary>
        /// return from string format all info by current license
        /// </summary>
        /// <returns></returns>
        public string GetAllLicenseInfo()
        {
            Debug.Log("------------- License info -------------");
            Debug.Log($"License key = {license.Key()}");
            Debug.Log($"Type = {license.Type()}");
            Debug.Log($"Status = {license.Status()}");
            Debug.Log($"IsTrial = {license.IsTrial()}");
            Debug.Log($"Max activations = {license.MaxActivations()}");
            Debug.Log($"Valid till = {license.ValidityPeriod()}");

            return "\n License type: " + license.Type() + "\n License status: " + license.Status() + "\n License is trial: " + license.IsTrial();
        }

        public bool DeactivateCurrentLicenseOnline()
        {
            try
            {
                return license.Deactivate();
            }
            catch (System.Exception ex)
            {
                sdkException?.Invoke(ex);
                return false;
            }
        }

        public string DesctivateCurrentLicenseOffline()
        {
            try
            {
                return license.DeactivateOffline();
            }
            catch (System.Exception ex)
            {
                sdkException?.Invoke(ex);
                return null;
            }
        }

        public string GetActivationFile(string licenseKey)
        {
            LicenseSpring.LicenseID key = LicenseID.FromKey(licenseKey);

            try
            {
                return licenseManager.GetOfflineActivationFile(key);
            }
            catch (System.Exception ex)
            {
                sdkException?.Invoke(ex);
                return null;
            }
        }

        public string GetActivationFile(string user, string password, string activationRequestFile)
        {
            LicenseSpring.LicenseID data = LicenseID.FromUser(user, password);

            try
            {
                return licenseManager.GetOfflineActivationFile(data, activationRequestFile);
            }
            catch (System.Exception ex)
            {
                sdkException?.Invoke(ex);
                return null;
            }
        }

        public int DaysPasset()
        {
            try
            {
                return license.DaysPassedSinceLastCheck();
            }
            catch (System.Exception ex)
            {
                sdkException?.Invoke(ex);
                return -1;
            }
        }

        public int DaysRemaining()
        {
            try
            {
                return license.DaysRemaining();
            }
            catch (System.Exception ex)
            {
                sdkException?.Invoke(ex);
                return -1;
            }
        }

        public int DaysRemainingUTC()
        {
            try
            {
                return license.DaysRemainingUTC();
            }
            catch (System.Exception ex)
            {
                sdkException?.Invoke(ex);
                return -1;
            }
        }

        #endregion

        #region Logs

        public void GetLogsGeneralData()
        {
            Debug.Log("------------- General info -------------");
            Debug.Log(licenseConfiguration.AppName + ' ' + licenseConfiguration.AppVersion);
            Debug.Log("LicenseSpring SDK version: " + licenseConfiguration.SdkVersion);
            Debug.Log("LicenseSpring API version: " + licenseConfiguration.LicenseSpringAPIVersion);
            Debug.Log("Determined OS version:     " + licenseConfiguration.OSVersion);
        }

        public void GetLogsNetworkStatus()
        {
            Debug.Log("------------- Network info -------------");
            Debug.Log("Host name:   " + licenseConfiguration.Hostname);
            Debug.Log("Local IP:    " + licenseConfiguration.LocalIp);
            Debug.Log("MAC address: " + licenseConfiguration.MACAddress);
        }

        public void GetLogsProductDetails()
        {
            Debug.Log("------------- Product Details -------------");
            Debug.Log("Product name:         " + productDetails.ProductName);
            Debug.Log("Product code:         " + productDetails.ProductCode);
            Debug.Log("Is trial allowed:     " + productDetails.IsTrialAllowed);
        }

        public void GetLogsTrialPeriod()
        {
            Debug.Log("Trial period (days):  " + productDetails.TrialPeriod);
        }

        public void GetLogsAuthirizationType()
        {
            if (productDetails.AuthorizationType == AuthorizationMethod.KeyBased)
            {
                Debug.Log("Authorization method: Key-based");
            }
            else
            {
                Debug.Log("Authorization method: User-based");
            }
        }

        public string InstallationFileToString(InstallationFile installationFile)
        {
            return "Md5Hash: " + installationFile.Md5Hash
                + "\nUrl: " + installationFile.Url
                + "\nVersion: " + installationFile.Version;
        }

        #endregion

        #endregion
    }

}