using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Collections.ObjectModel;

using Misc;
using FLY.Thick.Base.Common;
using FLY.Thick.Base.IService;
using FLY.Thick.RemoteHistory;

namespace FLY.Thick.Base.Server
{

    /// <summary>
    /// 报警管理系统
    /// </summary>
    public class WarningSystem : Misc.ISaveToXml, INotifyPropertyChanged, IWarningService, IWarningServiceSimple
    {
        FlyADBase.IFlyAD mflyad;
        int outIdxOfWarning=4;
        /// <summary>
        /// 报警灯 output 序号
        /// </summary>
        public int OutIdxOfWarning
        {
            get { return outIdxOfWarning; }
            set
            {
                if (outIdxOfWarning != value)
                {
                    outIdxOfWarning = value;
                    NotifyPropertyChanged("OutIdxOfWarning");
                }
            }
        }
        private int duration=5;
        public int Duration//持续时间，单位s， -1无限，永不停止
        {
            get { return duration; }
            set
            {
                if (duration != value)
                {
                    duration = value;
                    NotifyPropertyChanged("Duration");
                }
            }
        }

        private DateTime dtQuiet = DateTime.MinValue;

        private bool enable;
        public bool Enable//使能
        {
            get { return enable; }
            set
            {
                if (enable != value)
                {
                    enable = value;
                    NotifyPropertyChanged("Enable");
                }
            }
        }
        private bool ensave;
        public bool EnSave//是否保存
        {
            get { return ensave; }
            set
            {
                if( ensave != value)
                {
                    ensave = value;
                    NotifyPropertyChanged("EnSave");
                }
            }
        }
        private History<FlyData_WarningHistory> mHistory;

        /// <summary>
        /// 当前正在报警的！！！！！！
        /// </summary>
        private List<FlyData_WarningHistory> mCurr = new List<FlyData_WarningHistory>();

        private ObservableCollection<FlyData_WarningHistory> reasonlist = new ObservableCollection<FlyData_WarningHistory>();
        //PCList m_reasonList;//报警原因 列表
        public ObservableCollection<FlyData_WarningHistory> ReasonList { get { return reasonlist; } }

        private ObservableCollection<int> whitelist=new ObservableCollection<int>();
        /// <summary>
        /// /白名单，只响应白名单，优先执行白名单
        /// </summary>
        public ObservableCollection<int> WhiteList { get { return whitelist; } }

        private ObservableCollection<int> blacklist=new ObservableCollection<int>();
        /// <summary>
        /// /黑名单，里面的，都不响报警
        /// </summary>
        public ObservableCollection<int> BlackList { get { return blacklist; } }

        private string param_path = "warningsystem.xml";

        public WarningSystem()
        {
            Default();

            FObjBase.PollModule.Current.Poll_Config(FObjBase.PollModule.POLL_CONFIG.ADD,
                delegate()
                {
                    UpdateCurr();
                }, TimeSpan.FromSeconds(0.2));
        }

        public WarningSystem(string param_path)
        {
            if (!string.IsNullOrEmpty(param_path))
                this.param_path = param_path;

            Default();

            Load();

            FObjBase.PollModule.Current.Poll_Config(FObjBase.PollModule.POLL_CONFIG.ADD,
                delegate()
                {
                    UpdateCurr();
                }, TimeSpan.FromSeconds(0.2));
        }
        void Default() 
        {
            Enable = true;
            EnSave = false;
            mHistory = new History<FlyData_WarningHistory>("warning_history");
            mHistory.SaveRows = 500;
            OutIdxOfWarning = 4;
            Duration = 5;//持续时间 5s
        }
        public void Init(FlyADBase.IFlyAD flyad) 
        {
            mflyad = flyad;
        }
        /// <summary>
        /// 报警灯状态切换
        /// </summary>
        public void Reset()
        {
            if (Misc.MyBase.CHECKBIT(mflyad.OStatus, OutIdxOfWarning - 1))
            {
                Add(
                    ERRNOs.BASE_ERRNO_RINGTEST.Type,
                    ERRNOs.BASE_ERRNO_RINGTEST.Code,
                    ERRNOs.BASE_ERRNO_RINGTEST.Descrption,
                    ERR_STATE.ONCE);
            }
            else
            {
                Quiet();
            }
        }
        #region IWarningServiceSimple
        DateTime errtime=DateTime.MinValue;
        /// <summary>
        /// 当前报警 发生的时间
        /// </summary>
        public DateTime ErrTime
        {
            get {
                return errtime;
            }
            set 
            {
                if (errtime != value)
                {
                    errtime = value;
                    NotifyPropertyChanged("ErrTime");
                }
            }
        }

        byte errtype=0;
        /// <summary>
        /// 当前报警类型  0，没报警
        /// </summary>
        public byte ErrType 
        {
            get 
            {
                return errtype;
            }
            private set {
                if (errtype != value)
                {
                    errtype = value;
                    NotifyPropertyChanged("ErrType");
                }
            }
        }
        byte errcode=0;
        /// <summary>
        /// 报警编码
        /// </summary>
        public byte ErrCode 
        {
            get 
            {
                return errcode;
            }
            private set
            {
                if (errcode != value)
                {
                    errcode = value;
                    NotifyPropertyChanged("ErrCode");
                }
            }
        }
        string errdescription = "";
        /// <summary>
        /// 报警描述
        /// </summary>
        public string ErrDescription
        {
            get
            {
                return errdescription;
            }
            private set
            {
                if (errdescription != value)
                {
                    errdescription = value;
                    NotifyPropertyChanged("ErrDescription");
                }
            }
        }


        public void Add(byte errtype, byte errcode, string description, ERR_STATE state)
        {
            FlyData_WarningHistory reason = new Common.FlyData_WarningHistory();
            reason.Time = DateTime.Now;
            reason.ErrType = errtype;
            reason.ErrCode = errcode;
            reason.Description = description;
            reason.State = state;

            if (CheckValid(reason) == false)
                return;

            FlyData_WarningHistory error = null;
            if (mCurr.Count > 0)
                error = mCurr.Find(e => e.ErrType == errtype && e.ErrCode == errcode);
            
            switch (state)
            {
                case ERR_STATE.ONCE:
                    if (error == null)
                    {
                        mCurr.Add(reason.Clone());
                    }
                    else
                    {
                        error.State = state;
                        error.Time = reason.Time;
                        error.Description = reason.Description;
                    }
                    break;
                case ERR_STATE.ON:
                    if (error == null)
                    {
                        mCurr.Add(reason.Clone());
                    }
                    else
                    {
                        //已经有了，再发生，不管它。
                        return;
                    }
                    break;
                case ERR_STATE.OFF:
                    if (error == null) 
                    {
                        //没有在报警，不管它。
                        return;
                    }
                    else
                    {
                        error.State = state;
                        mCurr.Remove(error);
                    }
                    break;
            }



            ReasonList.Add(reason);
            if (ReasonList.Count > 20)
                ReasonList.RemoveAt(0);

            if (EnSave)
                mHistory.Add(reason);



            UpdateCurr();

        }
        public void Add(ERRNO errno, ERR_STATE state) 
        {
            Add(errno.Type, errno.Code, errno.Descrption, state);
        }
        #endregion

        public void Apply() 
        {
            Save();
        }
        public void Save()
        {
            Misc.SaveToXmlHepler.Save(param_path, this);
        }
        public bool Load()
        {
            return Misc.SaveToXmlHepler.Load(param_path, this);
        }
        void UpdateCurr() 
        {
            
            if (mCurr.Count > 0)
            {
                for (int i = 0; i < mCurr.Count; i++) 
                {
                    if (mCurr[i].State == ERR_STATE.ONCE) 
                    {
                        if (DateTime.Now - mCurr[i].Time > TimeSpan.FromSeconds(Duration)) 
                        {
                            mCurr.RemoveAt(i);
                            i--;
                        }
                    }
                }
            }
            if (mCurr.Count > 0)
            {
                FlyData_WarningHistory error = mCurr.Last();
                ErrTime = error.Time;
                ErrType = error.ErrType;
                ErrCode = error.ErrCode;
                ErrDescription = error.Description;
                if (ErrTime > dtQuiet)
                {
                    if(Enable)
                        Ring();
                }

            }
            else 
            {
                ErrType = 0;
                ErrCode = 0;
                ErrDescription = "";
                Quiet();
            }
        }
        bool CheckValid(FlyData_WarningHistory reason) 
        {

            //白名单，黑名单，只能有其一

            if (reason.ErrType == 0)//0 是本地的， 不能屏蔽
                return true;


            //白名单，只有白名单有的，才报警 
            int w_cnt = WhiteList.Count();
            if (w_cnt > 0)
            {
                if (!WhiteList.Contains(reason.ErrType))
                    return false;
                else
                    return true;
            }
            //黑名单，只有黑名单没有的，才报警
            int b_cnt = BlackList.Count();
            if (b_cnt > 0)
            {
                if (!BlackList.Contains(reason.ErrType))
                    return true;
                else
                    return false;
            }
            return true;
        }

        void Ring()
        {
            if (Misc.MyBase.CHECKBIT(mflyad.OStatus, OutIdxOfWarning - 1))
            {
                mflyad.SetOutput(
                    (UInt16)Misc.MyBase.BIT(OutIdxOfWarning - 1),
                    (UInt16)~Misc.MyBase.BIT(OutIdxOfWarning - 1));
            }
        }
        public void Quiet()
        {
            if (!Misc.MyBase.CHECKBIT(mflyad.OStatus, OutIdxOfWarning - 1))
            {
                dtQuiet = DateTime.Now;
                mflyad.SetOutput(
                    (UInt16)Misc.MyBase.BIT(OutIdxOfWarning - 1),
                    (UInt16)Misc.MyBase.BIT(OutIdxOfWarning - 1));
            }
        }

        #region INotifyPropertyChanged 成员
        protected void NotifyPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
                this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        public string[] GetSavePropertyNames()
        {
            return new string[]{
                "OutIdxOfWarning","Duration","Enable","EnSave","WhiteList","BlackList"};
        }
    }
}
