using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Policy;
using System.Text;
using System.Threading.Tasks;
using Microsoft.InformationProtection;
using Microsoft.InformationProtection.File;

namespace AipGateway.AIP
{
    public class LabelManager : AbstractManager
    {
        private IFileProfile _profile = null;
        private IFileEngine _engine = null;

        public LabelManager()
        {
        }
        ~LabelManager() => this.Dispose(false);
        public override void Dispose()
        {
            this.Dispose(true);
            GC.SuppressFinalize((object)this);
            
        }
        protected virtual void Dispose(bool disposing)
        {
            lock (this)
            {
                if (_profile != null & _engine != null)
                {
                    //_profile.UnloadEngineAsync(_engine.Settings.EngineId).Wait();
                }
                _engine = null;
                _profile = null;
            }
        }
        public override bool CreateProfile(ref MipContext mipContext)
        {
            try
            {
                var profileSettings = new FileProfileSettings(mipContext,
                    CacheStorageType.OnDiskEncrypted,
                    new ConsentDelegateImplementation());

                // IFileProfile은 특정 애플리케이션에 대한 모든 SDK 작업의 루트입니다.
                _profile = Task.Run(async () => await MIP.LoadFileProfileAsync(profileSettings)).Result;
            }
            catch (Exception e)
            {
                SetError(1, "LabelManager::CreateProfile Failed.", e.Message);
                return false;
            }
            return true;
        }

        public override bool CreateEngine(ref Identity identity, ref AuthDelegateImplementation authDelegate)
        {
            try
            {
                authDelegate.ResetError();
                // 보호 엔진 설정 개체를 만듭니다. 첫 번째 매개변수인 엔진 ID에 빈 문자열을 전달하면 SDK가 GUID를 생성합니다.
                // 이메일 주소나 기타 고유한 값을 전달하면 동일한 사용자에 대해 캐시된 엔진이 매번 로드되도록 하는 데 도움이 됩니다.
                // 로캘 설정은 지원되며 특히 클라이언트 응용 프로그램의 경우 컴퓨터 로캘을 기반으로 제공되어야 합니다.
                var engineSettings = new FileEngineSettings(identity.Email, authDelegate, "", "en-US")
                {
                    // Provide the identity for service discovery.
                    Identity = identity,
                    // Set ProtectionOnlyEngine to true for AD RMS as labeling isn't supported
                    //ProtectionOnlyEngine = true
                };

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

                Console.WriteLine(
                    "File Engine Sensitivity Labels ======================================================");
                var labels = _engine.SensitivityLabels;
                for (int ii = 0; ii < labels.Count; ii++)
                {
                    Console.WriteLine("{0}: {1}, {2}", ii.ToString(), labels[ii].Id + " : " + labels[ii].Name,
                        labels[ii].IsActive);
                    Label label = _engine.GetLabelById(labels[ii].Id);
                    if (label.Children.Count > 0)
                    {
                        for (int jj = 0; jj < label.Children.Count; jj++)
                        {
                            Console.WriteLine("\t{0}: {1}, {2}", jj.ToString(),
                                label.Children[jj].Id + " : " + label.Children[jj].Name, label.Children[jj].IsActive);
                        }
                    }
                    // Console.WriteLine("{0}: {1}, {2}, {3}, {4}, {5}", ii.ToString(), label.Id + " : " + label.Name, label.IsActive, 
                    //     label.Sensitivity, label.ActionSource, label.Description);
                }

                Console.WriteLine("=======================================================================");
            }
            catch (Exception e)
            {
                if (authDelegate.LastErrNo != 0)
                {
                    SetError(authDelegate.LastErrNo, "LabelManager::CreateEngine Failed.", authDelegate.LastErrMsg);
                }
                else
                {
                    SetError(2, "LabelManager::CreateEngine Failed.", e.Message);
                }
                return false;
            }

            return true;
        }
        public IEnumerable<Label> SensitivityLabels()
        {
            return _engine.SensitivityLabels;
        }

        private IFileHandler CreateFileHandler(string inputFile, string outputFile)
        {
            try
            {
                var handler = Task.Run(async () => await _engine.CreateFileHandlerAsync(inputFile, outputFile, true))
                    .Result;
                return handler;
            }
            catch (Exception ex)
            {
                SetError(91, "LabelManager::CreateFileHandler Failed.", ex.Message);
            }
            return null;
        }

        public AipLabel GetFileInfo(string fileName)
        {
            var handler = CreateFileHandler(fileName, fileName);
            if (handler == null)
            {
                return null;
            }

            return null;
        }

    }

}
