using FLY.OBJComponents.Client;
using FLY.OBJComponents.IService;
using FLY.Thick.Base.Common;
using FLY.Thick.Base.IService;
using FObjBase;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FLY.Thick.Base.UI
{

    public class PasswordAuthorize:INotifyPropertyChanged
    {
        const string JSONDIST_KEY = "password";
        /// <summary>
        /// 服务器
        /// </summary>
        IJsonDistService jsonDist;
        /// <summary>
        /// 数据库
        /// </summary>
        [PropertyChanged.DoNotCheckEquality]
        public PasswordJsonDb Db { get; private set; } = new PasswordJsonDb();

        PasswordJsonDb DbDefault;
        /// <summary>
        /// 修改时间，这个是服务器保存数据的时间。一切以服务器为准
        /// </summary>
        public DateTime Time { get; set; }

        public PasswordAuthorize(IJsonDistService jsonDist)
        {
            this.jsonDist = jsonDist;
            Load();
            if (jsonDist is FObjServiceClient)
            {
                var objServiceClient = jsonDist as FObjServiceClient;
                if (objServiceClient.IsConnected)
                {
                    //连接成功
                    fetch_db();
                }
                objServiceClient.PropertyChanged += ObjServiceClient_PropertyChanged;
            }
            else 
            {
                //运行在服务器，之间获取数据
                fetch_db();
            }

            jsonDist.ValueChanged += JsonDist_ValueChanged;

        }

        private void ObjServiceClient_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == nameof(FObjServiceClient.IsConnected)) 
            {
                var objServiceClient = sender as FObjServiceClient;
                if (objServiceClient.IsConnected)
                {
                    //连接成功
                    fetch_db();
                }
            }
        }
        private void JsonDist_ValueChanged(object sender, EventArgs _e)
        {
            var e = _e as JsonDistValueChangedEventArgs;
            if (e.key == JSONDIST_KEY)
            {
                fetch_db();
            }
        }



        void check_db() 
        {
            if (DbDefault == null)
                return;
            if (DbDefault.UiLvs.Count == 0)
                return;

            if (Db == null)
                Db = new PasswordJsonDb();

            // 界面权限
            foreach (var uiLv in DbDefault.UiLvs) {
                if (!Db.UiLvs.Any(u => u.UiName == uiLv.UiName)) {
                    Db.UiLvs.Add(new UiLvCell() { UiName = uiLv.UiName, Level = uiLv.Level, Description = uiLv.Description });
                }
            }

            //密码
            if (Db.Pws.Count() == 0) {
                foreach (var pw in DbDefault.Pws)
                {
                    Db.Pws.Add(new PasswordCell() { Password = pw.Password, Level=pw.Level, Description = pw.Description });
                }
            }
        }
        /// <summary>
        /// 从服务器获取数据
        /// </summary>
        void fetch_db() 
        {
            //连接成功
            this.jsonDist.GetValue(JSONDIST_KEY, (asyncContext, retData) =>
            {
                if (retData == null)
                {
                    //没有数据
                    //什么都不做
                }
                else 
                {
                    var distCell = (DistCell)retData;
                    var p = (distCell.Value).ToObject<PasswordJsonDb>();
                    if (p == null || p.Pws==null || p.Pws.Count()==0)//异常
                    {
                        //什么都不做
                    }
                    else 
                    {
                        //只要时间与服务器的不一样，全部覆盖！！
                        if (Time != distCell.Time) 
                        {
                            Time = distCell.Time;
                            Db = p;
                            check_db();
                            Save();
                            
                        }
                    }
                }
            }, this);
        }
        /// <summary>
        /// 推送数据到服务器
        /// </summary>
        void push_db(PasswordJsonDb db) 
        {
            this.jsonDist.SetValue(JSONDIST_KEY, JObject.FromObject(db));
        }

        /// <summary>
        /// 输入密码，确认密码权限是否满足要求， level越大，要求权限越大
        /// </summary>
        /// <param name="pw">密码</param>
        /// <param name="level">要求级别</param>
        /// <param name="pw_lv">输入密码的级别</param>
        /// <returns></returns>
        public AUTHORIZE_RESULT Authorize(string pw, int level, out int pw_lv)
        {
            return Authorize(pw, level, out pw_lv, out string pw_description);
        }
        /// <summary>
        /// 输入密码，确认密码权限是否满足要求， level越大，要求权限越大
        /// </summary>
        /// <param name="pw">密码</param>
        /// <param name="level">要求级别</param>
        /// <param name="pw_lv">输入密码的级别</param>
        /// <returns></returns>
        public AUTHORIZE_RESULT Authorize(string pw, int level, out int pw_lv, out string pw_description)
        {
            pw_lv = 0;
            pw_description = null;
            if (level <= 0)
                return AUTHORIZE_RESULT.OK;

            var v = from p in Db.Pws where p.Password == pw select p;
            if (v.Count() > 0)
            {
                var pwCell = v.First(); 
                pw_lv = pwCell.Level;
                pw_description = pwCell.Description;

                if (v.First().Level >= level)
                    return AUTHORIZE_RESULT.OK;
                else
                    return AUTHORIZE_RESULT.ERR_LEVEL;
            }
            return AUTHORIZE_RESULT.ERR_PW;
        }
        /// <summary>
        /// 输入密码，确认密码权限是否满足要求， level越大，要求权限越大
        /// </summary>
        /// <param name="pw"></param>
        /// <param name="uiName">界面名称</param>
        /// <returns></returns>
        public AUTHORIZE_RESULT Authorize(string pw, string uiName, out int pw_lv) 
        {
            return Authorize(pw, GetLv(uiName),out pw_lv);
        }
        /// <summary>
        /// 获取授权级别， 0级不需要密码就能通过
        /// </summary>
        /// <param name="uiName"></param>
        /// <returns></returns>
        public int GetLv(string uiName) 
        {
            Base.Common.UiLvCell uiLvCell;
            uiLvCell = Db.UiLvs.Find(c => c.UiName == uiName);
            if (uiLvCell == null)
            {
                uiLvCell = new Base.Common.UiLvCell()
                {
                    UiName = uiName
                };

                //没有，添加
                Db.UiLvs.Add(uiLvCell);
            }
            
            return uiLvCell.Level;
        }

        string file_path = "password.json";
        string file_default_path = "default/password.default.json";
        public event PropertyChangedEventHandler PropertyChanged;

        public void Apply(PasswordJsonDb db) 
        {
            //设置jsonDist，不需要设置到本地。 
            //jsonDist内的参数被修改后，会推送数据出来。到时再获取。
            push_db(db);
        }
        void Save()
        {
            //把密码都转为 byte 的数组。 再保存
            PasswordJsonDb db = null;
            {
                string json = Newtonsoft.Json.JsonConvert.SerializeObject(Db);
                db = Newtonsoft.Json.JsonConvert.DeserializeObject<PasswordJsonDb>(json); 
            };
            PasswordEncrypt(db);

            PasswordJsonDb2 p = new PasswordJsonDb2
            {
                Time = Time,
                Db = db
            };

            {
                string json = Newtonsoft.Json.JsonConvert.SerializeObject(p, Newtonsoft.Json.Formatting.Indented);

                try
                {
                    File.WriteAllText(file_path, json);
                }
                catch
                {

                } 
            }
        }
        /// <summary>
        /// 密码加密
        /// </summary>
        void PasswordEncrypt(PasswordJsonDb db) 
        {
            foreach (var pw in db.Pws)
            {
                string password = pw.Password;
                if (!string.IsNullOrEmpty(password))
                {
                    byte[] bs = System.Text.Encoding.ASCII.GetBytes(password);
                    pw.Password = Newtonsoft.Json.JsonConvert.SerializeObject(bs);
                }
            }
        }
        /// <summary>
        /// 密码解密
        /// </summary>
        void PasswordDecrypt(PasswordJsonDb db) 
        {
            
            foreach (var pw in db.Pws)
            {
                string password = pw.Password;
                if (!string.IsNullOrEmpty(password))
                {
                    try
                    {
                        byte[] bs = Newtonsoft.Json.JsonConvert.DeserializeObject<byte[]>(password);
                        password = System.Text.Encoding.ASCII.GetString(bs);
                        pw.Password = password;
                    }
                    catch
                    {

                    }
                }
            }
        }
        void LoadDefault() {
            if (!File.Exists(file_default_path))
                return;
            string json = File.ReadAllText(file_default_path);
            try
            {
                var db = Newtonsoft.Json.JsonConvert.DeserializeObject<PasswordJsonDb>(json);
                //翻译密码
                PasswordDecrypt(db);
                DbDefault = db;
            }
            catch
            {

            }
        }
        void Load()
        {
            LoadDefault();


            if (!File.Exists(file_path))
            {
                check_db();
                return;
            }
            

            string json = File.ReadAllText(file_path);
            try
            {
                var db = Newtonsoft.Json.JsonConvert.DeserializeObject<PasswordJsonDb2>(json);
                //翻译密码
                PasswordDecrypt(db.Db);
                Db = db.Db;
                Time = db.Time;
                check_db();
            }
            catch {
            
            }
        }
    }

    /// <summary>
    /// 授权输入返回结果
    /// </summary>
    public enum AUTHORIZE_RESULT
    {
        /// <summary>
        /// 成功
        /// </summary>
        OK,
        /// <summary>
        /// 不够级别
        /// </summary>
        ERR_LEVEL,
        /// <summary>
        /// 密码出错
        /// </summary>
        ERR_PW
    }


    public class PasswordJsonDb2
    {
        /// <summary>
        /// 与服务器同步参数
        /// </summary>
        public PasswordJsonDb Db;

        /// <summary>
        /// 修改时间
        /// </summary>
        public DateTime Time;
    }
    public class PasswordJsonDb
    {
        /// <summary>
        /// 界面授权列表
        /// </summary>
        public List<UiLvCell> UiLvs { get; } = new List<UiLvCell>();

        /// <summary>
        /// 密码列表
        /// </summary>
        public List<PasswordCell> Pws { get; } = new List<PasswordCell>();
    }

}
