using Foresight.ServiceModel;
using IronIntel.Contractor.Users;
using IronIntel.Services;
using IronIntel.Services.CredentialObjects;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace IronIntel.Contractor.Site
{
    public class CredentialEntryBasePage : ContractorBasePage
    {
        private const string AEMP = "AEMPFLEET";
        private const string JDAPI = "JDAPI";
        protected void ProcessRequest(string methodName)
        {
            if (methodName != null)
            {
                switch (methodName)
                {
                    case "GetCredentials":
                        GetCredentials();
                        break;
                    case "SaveCredential":
                        SaveCredential(true);
                        break;
                    case "DeleteCredential":
                        DeleteCredential();
                        break;
                    case "GetAEMPSources":
                        GetAEMPSources();
                        break;
                    case "GetJDLinkCredentials":
                        GetJDLinkCredentials();
                        break;
                    case "AuthorizeRequestToken":
                        AuthorizeRequestToken();
                        break;
                    case "FinishJDLinkOAuthRequest":
                        FinishJDLinkOAuthRequest();
                        break;
                }
            }

            Response.End();
        }

        protected override bool AllowCurrentLoginSessionEnter()
        {
            var f = base.AllowCurrentLoginSessionEnter();
            if (!f)
            {
                return false;
            }

            // check whether you are admin.
            var session = GetCurrentLoginSession();
            if (session == null || session.User == null)
            {
                return false;
            }
            var ui = UserManagement.GetUserByIID(session.User.UID);
            return ui != null && ui.UserType >= UserTypes.Admin;
        }

        protected override bool ThrowIfNotAllowed { get { return true; } }

        private void GetCredentials()
        {
            string type = Request.Form["ClientData"];
            string creType = "";
            switch (type)
            {
                case "AEMP":
                    creType = AEMP;
                    break;
            }
            CredentialManagementClient crd = SystemParams.GetServiceClient<CredentialManagementClient>();
            CredentialInfo[] creInfos = crd.GetCredentialByCompanyID(SystemParams.CompanyID, creType);

            List<CredentialObj> creObjs = new List<CredentialObj>();
            foreach (var cre in creInfos)
            {
                creObjs.Add(ConvertFromAEMP(cre));
            }
            var items = creObjs.OrderBy((c) => c.UserName).ToArray();
            string json = JsonConvert.SerializeObject(items);
            Response.Write(json);
            Response.End();
        }

        private void SaveCredential(bool adduser)
        {
            var content = Request.Form["ClientData"];
            content = HttpUtility.HtmlDecode(content);
            var item = JsonConvert.DeserializeObject<CredentialObj>(content);

            try
            {
                if (string.IsNullOrEmpty(item.ID))
                    item.ID = Guid.NewGuid().ToString();
                CredentialInfo creInfo = null;
                switch (item.CredentialType)
                {
                    case "AEMP":
                        creInfo = ConvertToAEMP(item);
                        break;
                }
                if (creInfo != null)
                {
                    CredentialManagementClient crd = SystemParams.GetServiceClient<CredentialManagementClient>();
                    crd.UpdateCredential(creInfo);
                }
            }
            catch (Exception ex)
            {
                Response.Write(JsonConvert.SerializeObject(ex.Message));
                return;
            }

            Response.Write("\"OK\"");
        }

        private void DeleteCredential()
        {
            var iid = Request.Form["ClientData"];
            Guid guid;
            if (!Guid.TryParse(iid, out guid))
            {
                throw new ArgumentException("Credential IID is not valid.");
            }
            CredentialManagementClient crd = SystemParams.GetServiceClient<CredentialManagementClient>();
            crd.DeleteCredential(iid);
        }

        private void GetAEMPSources()
        {
            IronSysServiceClient ic = SystemParams.GetIronSystemServiceClient();
            AEMPSourceInfo[] sources = ic.GetAEMPSourceInfo();

            List<AEMPSourceItem> list = new List<AEMPSourceItem>();
            foreach (var source in sources)
            {
                AEMPSourceItem item = new AEMPSourceItem();
                Helper.CloneProperty(item, source);
                list.Add(item);
            }
            var items = list.OrderBy((c) => c.ManufactureName).ToArray();
            string json = JsonConvert.SerializeObject(items);
            Response.Write(json);
            Response.End();
        }

        #region AEMP

        private CredentialObj ConvertFromAEMP(CredentialInfo cre)
        {
            CredentialObj result = new CredentialObj();
            result.ID = cre.ID;
            result.CredentialType = cre.CredentialType;

            AEMPCredential aemp = new AEMPCredential();
            aemp.FillFromXml(cre.Credential);
            if (aemp != null)
            {
                result.Manufacture = aemp.ManufactureID;
                result.UserName = aemp.UserName;
                result.Password = aemp.Password;
                result.Enabled = aemp.Enabled;
                result.UrlKey = aemp.UrlKey;
                result.OrgnizationID = aemp.OrgnizationID;
            }

            return result;
        }

        private CredentialInfo ConvertToAEMP(CredentialObj cre)
        {
            CredentialInfo result = new CredentialInfo();
            result.ID = cre.ID;
            result.CredentialType = AEMP;
            result.CompanyID = SystemParams.CompanyID;

            AEMPCredential aemp = new AEMPCredential();
            aemp.ManufactureID = cre.Manufacture;
            aemp.UserName = cre.UserName;
            aemp.Password = cre.Password;
            aemp.Enabled = cre.Enabled;
            aemp.UrlKey = cre.UrlKey;
            aemp.OrgnizationID = cre.OrgnizationID;

            result.Credential = aemp.ToString();

            return result;
        }

        #endregion

        #region JDLink credential
        private void GetJDLinkCredentials()
        {
            CredentialManagementClient client = SystemParams.GetServiceClient<CredentialManagementClient>();
            JDCredential[] jds = client.GetJDLinkCredentials(SystemParams.CompanyID);
            List<JDCredentialObj> list = new List<JDCredentialObj>();
            foreach (var jd in jds)
            {
                JDCredentialObj item = new JDCredentialObj();
                item.ID = jd.ID;
                item.UserName = jd.Credential.UserName;
                item.ExpirationDateUtc = jd.Credential.ExpirationDateUtc;
                item.ConsumerKey = jd.Credential.ConsumerKey;
                item.AuthorityUrl = jd.Credential.AuthorityUrl;
                list.Add(item);
            }
            var items = list.OrderBy(m => m.UserName).ToArray();
            string json = JsonConvert.SerializeObject(items);
            Response.Write(json);
            Response.End();
        }

        private void AuthorizeRequestToken()
        {
            string username = Request.Form["ClientData"];
            username = HttpUtility.HtmlDecode(username);
            CredentialManagementClient client = SystemParams.GetServiceClient<CredentialManagementClient>();
            JDCredential[] jds = client.GetJDLinkCredentials(SystemParams.CompanyID);
            JDCredential jd = jds.FirstOrDefault(m => m.Credential.UserName == username);
            if (jd != null)
            {
                Response.Write(JsonConvert.SerializeObject("User name already exists."));
                Response.End();
            }
            StringKeyValue kv = GetJDLinkApiKey();
            if (kv == null)
            {
                Response.Write(JsonConvert.SerializeObject("The JDLink Key does not exist,Please contact the administrator."));
                Response.End();
            }
            JDOAuthData data = client.GetJDLinkAuthorizeRequestOAuth(kv.Key, kv.Value);
            string json = JsonConvert.SerializeObject(data);
            Response.Write(json);
            Response.End();
        }

        public void FinishJDLinkOAuthRequest()
        {
            try
            {
                var clientdata = Request.Form["ClientData"].Split((char)170);
                var authordata = HttpUtility.HtmlDecode(clientdata[0]);
                string virifier = HttpUtility.HtmlDecode(clientdata[1]);

                JDOAuthData oriauthdata = JsonConvert.DeserializeObject<JDOAuthData>(authordata);
                CredentialManagementClient client = SystemParams.GetServiceClient<CredentialManagementClient>();
                JDOAuthData data = client.FinishJDLinkOAuthRequest(oriauthdata, virifier);
                CredentialInfo ci = new CredentialInfo();
                ci.ID = Guid.NewGuid().ToString().ToUpper();
                ci.CompanyID = SystemParams.CompanyID;
                ci.CredentialType = "JDLINK";
                JDCredential jd = new JDCredential();
                jd.Credential = data;
                jd.Enabled = true;
                ci.Credential = jd.ToString();
                client.UpdateCredential(ci);
            }
            catch (Exception ex)
            {
                Response.Write(JsonConvert.SerializeObject(ex.Message));
                return;
            }

            Response.Write("\"OK\"");
        }

        private StringKeyValue GetJDLinkApiKey()
        {
            string key = SystemParams.GetStringParam("JDAPIConsumerKey");
            if (string.IsNullOrWhiteSpace(key))
            {
                return null;
            }
            string sec = SystemParams.GetStringParam("JDAPIConsumerSecret");
            if (string.IsNullOrWhiteSpace(sec))
            {
                return null;
            }
            StringKeyValue kv = new StringKeyValue();
            kv.Key = key;
            kv.Value = sec;
            return kv;
        }


        #endregion

        /// <summary>
        /// 用于传输的临时Credential类
        /// </summary>
        public class CredentialObj
        {
            public string ID { get; set; }
            public string CredentialType { get; set; }
            public string Manufacture { get; set; }
            public string UrlKey { get; set; }
            public string UserName { get; set; }
            public string Password { get; set; }
            public bool Enabled { get; set; }
            public string OrgnizationID { get; set; }
        }

        public class AEMPSourceItem
        {
            public string ManufactureID { get; set; }
            public string ManufactureName { get; set; }
            public string FleetUrl { get; set; }
            public string AutoServiceClass { get; set; }
        }

        public class JDCredentialObj
        {
            public string ID { get; set; }
            public string UserName { get; set; }
            public string ConsumerKey { get; set; }
            public string AuthorityUrl { get; set; }
            public DateTime ExpirationDateUtc { get; set; }
            public string ExpirationDateUtcStr { get { return ExpirationDateUtc == DateTime.MinValue ? "" : ExpirationDateUtc.ToShortDateString(); } }
        }
    }
}
