using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.InformationProtection;
using Microsoft.InformationProtection.Protection;

namespace AipGateway.AIP
{
    public class ProtectionManager : AbstractManager
    {
        private IProtectionProfile _profile = null;
        private IProtectionEngine _engine = null;
        public ProtectionManager()
        {
        }
        ~ProtectionManager() => this.Dispose(false);

        public override void Dispose()
        {
            this.Dispose(true);
            GC.SuppressFinalize((object)this);

        }
        protected virtual void Dispose(bool disposing)
        {
            lock (this)
            {
                if (_engine != null) _engine.Dispose();
                if (_profile != null) _profile.Dispose();
                _profile = null;
                _engine = null;
            }
        }

        public override bool CreateProfile(ref MipContext mipContext)
        {
            try
            {
                var profileSettings = new ProtectionProfileSettings(mipContext,
                    CacheStorageType.OnDisk,
                    new ConsentDelegateImplementation());

                // IProtectionProfile은 특정 애플리케이션에 대한 모든 SDK 작업의 루트입니다.
                _profile = MIP.LoadProtectionProfile(profileSettings);
            }
            catch (Exception e)
            {
                SetError(1, "ProtectionManager::CreateProfile Failed.", e.Message);
                return false;
            }
            return _profile != null;
        }

        public override bool CreateEngine(ref Identity identity, ref AuthDelegateImplementation authDelegate)
        {
            try
            {
                authDelegate.ResetError();
                var engineSettings = new ProtectionEngineSettings(identity.Email, authDelegate, string.Empty, "")
                {
                    Identity = identity
                };

                _engine = Task.Run(async () => await _profile.AddEngineAsync(engineSettings)).Result;

                //Console.WriteLine("Protection Engine Templates ======================================================");
                //var templates = _engine.GetTemplates();
                //for (int ii = 0; ii < templates.Count; ii++)
                //{
                //    Console.WriteLine("{0}: {1}, {2}", ii.ToString(), templates[ii].Id + " : " + templates[ii].Name, templates[ii].Description);
                //}
                //Console.WriteLine("=======================================================================");
            }
            catch (Exception e)
            {
                if (authDelegate.LastErrNo != 0)
                {
                    SetError(authDelegate.LastErrNo, "ProtectionManager::CreateEngine Failed.", authDelegate.LastErrMsg);
                }
                else
                {
                    SetError(2, "ProtectionManager::CreateEngine Failed.", e.Message);
                }

                return false;
            }
            return _engine != null;
        }
        
        public List<TemplateDescriptor> GetTemplates()
        {
            return _engine.GetTemplates();
        }

        public IProtectionHandler CreatePublishingProtectionHandler(string templateId)
        {
            ProtectionDescriptor protectionDescriptor = new ProtectionDescriptor(templateId);
            PublishingSettings publishingSettings = new PublishingSettings(protectionDescriptor);

            IProtectionHandler protectionHandler = null;
            try
            {
                protectionHandler = _engine.CreateProtectionHandlerForPublishing(publishingSettings);
            }
            catch (Exception ex)
            {
                SetError(51, "ProtectionManager::CreatePublishingProtectionHandler Failed.", ex.Message);
            }
            return protectionHandler;
        }

        // Create a handler for consumption from the publishing license.
        public IProtectionHandler CreateConsumptionProtectionHandler(List<byte> serializedPublishingLicense, MipContext mipContext, string comments)
        {
            PublishingLicenseInfo plInfo = PublishingLicenseInfo.GetPublishingLicenseInfo(serializedPublishingLicense, mipContext);

            ConsumptionSettings consumptionSettings = new ConsumptionSettings(plInfo)
            {
                // This is a new required field for tracking content for Track and Revoke. 
                ContentName = comments
            };

            IProtectionHandler protectionHandler = null;
            try
            {
                protectionHandler = _engine.CreateProtectionHandlerForConsumption(consumptionSettings);
            }
            catch (Exception ex)
            {
                SetError(52, "ProtectionManager::CreateConsumptionProtectionHandler Failed.", ex.Message);
            }
            return protectionHandler;
        }
        public byte[] Protect(IProtectionHandler handler, byte[] data)
        {
            long buffersize = handler.GetProtectedContentLength(data.Length, true);
            byte[] outputBuffer = new byte[buffersize];

            handler.EncryptBuffer(0, data, outputBuffer, true);
            return outputBuffer;
        }

        public byte[] Unprotect(IProtectionHandler handler, byte[] data)
        {
            long buffersize = data.Length;
            byte[] clearBuffer = new byte[buffersize];

            var bytesDecrypted = handler.DecryptBuffer(0, data, clearBuffer, true);

            byte[] outputBuffer = new byte[bytesDecrypted];
            for (int i = 0; i < bytesDecrypted; i++)
            {
                outputBuffer[i] = clearBuffer[i];
            }

            return outputBuffer;
        }

        public bool SetProtect(string fileName, string actualFileName, string email, string templateId, string comments)
        {
            // var outFileName = actualFileName == string.Empty ? fileName : actualFileName;
            // var handler = CreateFileHandler(fileName, outFileName);
            // if (handler == null)
            // {
            //     return false;
            // }
            //
            // var publishHandler = CreatePublishingProtectionHandler(templateId);
            // if (publishHandler == null)
            // {
            //     return false;
            // }
            //
            //
            // var protectionDescriptor = new ProtectionDescriptor(templateId);
            //
            // try
            // {
            //     handler.SetProtection(new ProtectionDescriptor(templateId));
            // }
            // catch (Exception ex)
            // {
            //     SetError(52, "FileManager::SetLabel Failed.", ex.Message);
            //     return false;
            // }
            //
            // bool result = false;
            // if (handler.IsModified())
            // {
            //     result = Task.Run(async () => await handler.CommitAsync(outFileName)).Result;
            // }
            //
            // if (result)
            // {
            //     handler.NotifyCommitSuccessful(fileName);
            // }
            // else
            // {
            //     SetError(53, "FileManager::SetProtect Failed.", "Template Id: " + templateId + ", SetProtect Failed.");
            // }
            // return result;
            return true;
        }

        public void GetTemplateById(string templateId)
        {
        }
    }
}
