using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Threading;
using System.ComponentModel;
using System.IO;

namespace FLY.Thick.RemoteHistory
{
    public class Buffer<T> : IBuffer<T>
        where T : IFlyData, new()
    {
        DispatcherTimer timer;

        private int SaveInterval = 1;
        private bool hasnew = false;
        public bool HasNew
        {
            get { return hasnew; }
            set
            {
                if (hasnew != value)
                {
                    hasnew = value;
                    NotifyPropertyChanged("HasNew");
                }
            }
        }
        private string FilePath;

        #region IBuffer<T>
        private int size = 400;
        public int Size
        {
            get { return size; }
            set
            {
                if (value < 100)
                    value = 100;
                if (size != value)
                {
                    size = value;
                    NotifyPropertyChanged("Size");
                }
            }
        }
        private List<T> record = new List<T>();
        /// <summary>
        /// 每次配料记录
        /// </summary>
        public List<T> Record
        {
            get
            {
                return record;
            }
        }
        #endregion
        public void Init(string filepath)
        {
            Init(filepath, false);
        }
        public void Init(string filepath, bool save_immediately)
        {
            FilePath = filepath;
            Load();
            if (save_immediately)
                SaveInterval = 0;

            if (SaveInterval > 0)
            {
                timer = new DispatcherTimer();
                timer.Interval = TimeSpan.FromMinutes(SaveInterval);
                timer.Tick += new EventHandler(timer_Tick);
                timer.Start();
            }

            this.PropertyChanged += Buffer_PropertyChanged;
        }

        public void Add(T t)
        {
            Record.Add(t);
            while (Record.Count() > Size)
            {
                Record.RemoveAt(0);
            }
            HasNew = true;
            NotifyRecordChanged(true, 1);
        }
        public void Remove(T t)
        {
            Record.Remove(t);
            HasNew = true;
            NotifyRecordChanged(false, Record.Count);
        }
        public void Clear()
        {
            Record.Clear();
            HasNew = true;
            NotifyRecordChanged(false, 0);
        }
        public void Flush()
        {
            Save();
        }
        void Buffer_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "HasNew")
            {
                if (HasNew)
                {
                    if (SaveInterval <= 0)
                    {
                        Save();
                    }
                }
            }
        }
        /// <summary>
        /// N分钟执行一次
        /// </summary>
        void timer_Tick(object sender, EventArgs e)
        {
            if (HasNew)
            {
                Save();
            }
        }

        void Load()
        {
            if (string.IsNullOrEmpty(FilePath))
                return;
            Record.Clear();
            HasNew = false;
            try
            {
                using (StreamReader sr = new StreamReader(FilePath, Encoding.GetEncoding("GB2312")))
                {
                    string header = sr.ReadLine();
                    if (string.IsNullOrEmpty(header))
                        return;

                    while (!sr.EndOfStream)
                    {
                        T t = new T();
                        if (t.TryParse(header, sr.ReadLine()))
                        {
                            Record.Add(t);
                        }
                    }
                }
            }
            catch (Exception e)
            {

            }

        }
        void Save()
        {
            if (string.IsNullOrEmpty(FilePath))
                return;

            if (!HasNew)
                return;

            HasNew = false;

            if (Record.Count() == 0)
            {
                //删除掉文件
                File.Delete(FilePath);
                return;
            }



            //以附加的方式打开只写文件。
            //若文件不存在，则会建立该文件，
            //如果文件存在，写入的数据会被加到文件尾，即文件原先的内容会被保留。
            using (StreamWriter sw = new StreamWriter(FilePath, false, Encoding.GetEncoding("GB2312")))
            {
                sw.WriteLine(Record[0].GetHeader());
                for (int i = 0; i < Record.Count; i++)
                    sw.WriteLine(Record[i].ToString());
                sw.Flush();
                sw.Close();
            }
        }

        #region IBuffer<T>
        public event BufferChangedEventHandler RecordChanged;
        #endregion

        public void NotifyRecordChanged(bool isAdd, int cnt)
        {
            if (RecordChanged != null)
            {
                RecordChanged.Invoke(Record, new BufferChangedEventArgs(isAdd, cnt));
            }
        }

        #region INotifyPropertyChanged 成员

        public event PropertyChangedEventHandler PropertyChanged;
        protected void NotifyPropertyChanged(string propertyname)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyname));
            }
        }
        #endregion
    }
}
