using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Text.RegularExpressions;
using System.Collections.ObjectModel;
using System.IO;
using FLY.Thick.Base.Common;
using System.Net;
using FLY.Thick.Base.OBJ_INTERFACE;


namespace ThickTcpUiInWindow
{
    /// <summary>
    /// Window_RemoteHistory.xaml 的交互逻辑
    /// </summary>
    public partial class Window_RemoteHistory : Window, INotifyPropertyChanged
    {

        FLY.Thick.RemoteHistory.RemoteHistorySerivceClient mRemoteHistoryService = null;

        OBJ_FileBus.Client_OBJProxy mClientService = null;

        OBJ_FileBus.ClientAdv mClient = null;
        #region 搜索条件
        DateTime begindate;

        public DateTime BeginDate
        {
            get { return begindate; }
            set
            {
                if (begindate != value)
                {
                    begindate = value;
                    NotifyPropertyChanged("BeginDate");
                }
            }
        }

        DateTime enddate;

        public DateTime EndDate
        {
            get { return enddate; }
            set
            {
                if (enddate != value)
                {
                    enddate = value;
                    NotifyPropertyChanged("EndDate");
                }
            }
        }

        string productnamefilter;
        /// <summary>
        /// 产品名过滤
        /// </summary>
        public string ProductNameFilter
        {
            get { return productnamefilter; }
            set
            {
                if (productnamefilter != value)
                {
                    productnamefilter = value;
                    NotifyPropertyChanged("ProductNameFilter");
                }
            }
        }
        #endregion

        string productname;
        /// <summary>
        /// 当前所选的产品
        /// </summary>
        public string ProductName
        {
            get { return productname; }
            set
            {
                if (productname != value)
                {
                    productname = value;
                    NotifyPropertyChanged("ProductName");
                }
            }
        }
        /// <summary>
        /// 服务器筛选后的名字列表
        /// </summary>
        List<string> FileList = new List<string>();

        class FileProgress : INotifyPropertyChanged
        {

            string filepath;

            public string FilePath
            {
                get { return filepath; }
                set
                {
                    if (filepath != value)
                    {
                        filepath = value;
                        NotifyPropertyChanged("FilePath");
                    }
                }
            }

            int downloadsize = 0;

            public int DownloadSize
            {
                get { return downloadsize; }
                set
                {
                    if (downloadsize != value)
                    {
                        downloadsize = value;
                        NotifyPropertyChanged("DownloadSize");
                    }
                }
            }

            int size = -1;

            public int Size
            {
                get { return size; }
                set
                {
                    if (size != value)
                    {
                        size = value;
                        NotifyPropertyChanged("Size");
                    }
                }
            }





            protected void NotifyPropertyChanged(string propertyName)
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
                }
            }


            public event PropertyChangedEventHandler PropertyChanged;
        }
        /// <summary>
        /// 产品对应的列表
        /// </summary>
        ObservableCollection<FileProgress> ResultList = new ObservableCollection<FileProgress>();
        /// <summary>
        /// 产品列表
        /// </summary>
        ObservableCollection<string> ProductNameList = new ObservableCollection<string>();

        Type mWindowHistoryReaderType;
        public Window_RemoteHistory()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="serverep"></param>
        /// <param name="serverid">FLY.Thick.OBJ_INTERFACE.OBJ_INTERFACE_ID.REMOTEHISTORY_ID</param>
        /// <param name="windowHistoryReaderType"></param>
        public void Init(IPEndPoint serverep, UInt32 serverid, Type windowHistoryReaderType)
        {
            //FLY.Thick.OBJ_INTERFACE.OBJ_INTERFACE_ID.REMOTEHISTORY_ID
            mRemoteHistoryService = new FLY.Thick.RemoteHistory.RemoteHistorySerivceClient(
                serverid);

            mWindowHistoryReaderType = windowHistoryReaderType;

            FObjBase.FObjSys.Current.Connect_to_Another_OBJSys(
                serverep, mRemoteHistoryService.ID);

            //判断本地，还是远端
            if (!serverep.Address.Equals(IPAddress.Parse("127.0.0.1")))
            {
                mClient = new OBJ_FileBus.ClientAdv(Misc.StringConverter.IPEndPoint2DirectoryName(serverep));
                mClientService = new OBJ_FileBus.Client_OBJProxy(mClient.mClient);

                FObjBase.FObjSys.Current.Connect_to_Another_OBJSys(
                    serverep, mClientService.ID);
            }
        }
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {

            BeginDate = DateTime.Now.AddDays(-1);
            EndDate = DateTime.Now;

            stackpanel_state.DataContext = mRemoteHistoryService;
            grid_list.DataContext = this;


            progressBar1.DataContext = this.mReadService;
            comboBox1.ItemsSource = ProductNameList;

            listBox1.ItemsSource = ResultList;

        }
        void mReadService_StopEventForShow(ReadService sender)
        {
            switch (sender.ReadState)
            {
                case ReadService.READSTATE.OK:
                    {
                        var v = from rp in sender.ReadPaths select mClient.RootPath + rp.Path;
                        Read(v);
                    } break;
            }
        }

        private void Window_Unloaded(object sender, RoutedEventArgs e)
        {
            mReadService.Stop();
            if (mClient != null)
                mClient.FreeComm(this);
            if (mClientService != null)
                mClientService.Dispose();
            mRemoteHistoryService.Dispose();
        }

        private void button_rolldown_Click(object sender, RoutedEventArgs e)
        {
            mRemoteHistoryService.Flush();
        }

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

        private void button_search_Click(object sender, RoutedEventArgs e)
        {
            mRemoteHistoryService.GetPaths(
                BeginDate, EndDate, ProductNameFilter,
                new FLY.Thick.RemoteHistory.GetPathsReponseHandler(
                    delegate(List<string> filepaths, object state)
                    {
                        FileList = filepaths;
                        UpdateProductNameList();
                    }), null);
        }
        /// <summary>
        /// 从FileList，提取productname，放入ProductNameList
        /// </summary>
        void UpdateProductNameList()
        {
            ProductNameList.Clear();
            foreach (string path in FileList)
            {
                Regex regex_file = new Regex(@"\d{2}_\d{2}_\d{2}.*\.csv");
                Match match = regex_file.Match(path);

                string productname;
                Regex regex_header = new Regex(@"\d{2}_\d{2}_\d{2}_");
                int idx = 8;
                if (regex_header.IsMatch(match.Value))
                    idx = 9;
                productname = match.Value.Substring(idx, match.Value.Length - idx - 4);
                if (!ProductNameList.Contains(productname))
                    ProductNameList.Add(productname);
            }
            if (ProductNameList.Count > 0)
            {
                ProductName = ProductNameList.First();
                comboBox1.SelectedItem = ProductName;
            }
            UpdateResultList();
        }
        List<string> download_paths = new List<string>();
        void Read(IEnumerable<string> paths)
        {
            IWindowHistoryReader wr = Activator.CreateInstance(mWindowHistoryReaderType) as IWindowHistoryReader;
            wr.ShowDialog(paths, ProductName);
            //Window_HistoryScan2 w = new Window_HistoryScan2();

            //foreach(string path in paths)
            //{
            //    w.Paths.Add(path);
            //}
            //w.ProductName = ProductName;
            //w.ShowDialog();
        }
        private void button_read_Click(object sender, RoutedEventArgs e)
        {
            if (listBox1.SelectedItems.Count == 0)
                return;

            mReadService.Stop();
            download_paths.Clear();

            for (int i = 0; i < listBox1.SelectedItems.Count; i++)
            {
                download_paths.Add((listBox1.SelectedItems[i] as FileProgress).FilePath);
            }

            if (mClient != null)//网络版
            {

                mReadService.Start(download_paths, new ReadService.StopHandler(mReadService_StopEventForShow));

                GetDownloadFile(0);
            }
            else
            {
                //本地版
                mRemoteHistoryService.GetRootPath(new FLY.Thick.RemoteHistory.GetRootPathReponseHandler(delegate(string rootpath, object state)
                {
                    var v = from s in download_paths select rootpath + @"\" + s;
                    Read(v);
                }), null);
            }
        }
        private void GetDownloadFile(int index)
        {

            string filepath = download_paths[index];//paths[i] as string;

            mClient.ReadFile(filepath, this, new EventHandler(delegate(object sender2, EventArgs e2)
            {
                string path;
                OBJ_FileBus.ERRNO ret;
                if (e2 is OBJ_FileBus.Client.ReadInfoEventArgs)
                {

                    OBJ_FileBus.Client.ReadInfoEventArgs ea = e2 as OBJ_FileBus.Client.ReadInfoEventArgs;
                    path = ea.mPath;
                    ret = ea.mErrno;

                }
                else if (e2 is OBJ_FileBus.Client.ReadEventArgs)
                {
                    OBJ_FileBus.Client.ReadEventArgs ea = e2 as OBJ_FileBus.Client.ReadEventArgs;
                    path = ea.mPath;
                    ret = ea.mErrno;

                }
                else
                {
                    return;
                }

                switch (ret)
                {
                    case OBJ_FileBus.ERRNO.OK:
                        {
                            OBJ_FileBus.FileElement fe = mClient.Root.SelectSingleNode(path);
                            FileProgress fp = ResultList.First(_fp => _fp.FilePath == path);
                            fp.DownloadSize = fe.DownloadSize;
                            fp.Size = fe.Size;
                            mReadService.Touch(path, ReadService.FILEREAD_STATE.OK, fe.DownloadSize, fe.Size);
                            int idx = download_paths.FindIndex(s => s == path);
                            idx++;
                            if (idx < (download_paths.Count()))
                                GetDownloadFile(idx);

                        } break;
                    case OBJ_FileBus.ERRNO.DOING:
                        {
                            OBJ_FileBus.FileElement fe = mClient.Root.SelectSingleNode(path);
                            FileProgress fp = ResultList.First(_fp => _fp.FilePath == path);
                            fp.DownloadSize = fe.DownloadSize;
                            fp.Size = fe.Size;
                            mReadService.Touch(path, ReadService.FILEREAD_STATE.READING, fe.DownloadSize, fe.Size);

                        } break;
                    default:
                        {
                            mReadService.Touch(path, ReadService.FILEREAD_STATE.ERR);
                            int idx = download_paths.FindIndex(s => s == path);
                            idx++;
                            if (idx < (download_paths.Count()))
                                GetDownloadFile(idx);
                        } break;
                }
            }));
        }

        private void button_selsectall_Click(object sender, RoutedEventArgs e)
        {
            listBox1.SelectAll();
        }
        private void comboBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (comboBox1.SelectedItem != null)
            {
                ProductName = (string)comboBox1.SelectedItem;
                UpdateResultList();
            }
        }
        void UpdateResultList()
        {
            ResultList.Clear();
            string filter_str = ProductName;
            Regex regex_filter;
            if (string.IsNullOrEmpty(filter_str))
            {
                regex_filter = new Regex(@"\d{2}_\d{2}_\d{2}\.csv");
            }
            else
            {
                string unescape = Regex.Escape(filter_str);
                regex_filter = new Regex(@"\d{2}_\d{2}_\d{2}_" + unescape + @"\.csv");
            }

            foreach (string path in FileList)
            {
                if (regex_filter.IsMatch(path))
                {
                    FileProgress fp = new FileProgress() { FilePath = @"\" + path };
                    ResultList.Add(fp);
                }
            }

        }
        class ReadService : INotifyPropertyChanged
        {
            public enum FILEREAD_STATE
            {
                OK,
                READING,
                ERR
            }
            public class FileRead
            {
                public string Path;
                public int DownloadSize = 0;
                public int Size = -1;
                public FILEREAD_STATE State = FILEREAD_STATE.READING;
            }

            double progress = 0;
            /// <summary>
            /// 0~100
            /// </summary>
            public double Progress
            {
                get { return progress; }
                set
                {
                    if (progress != value)
                    {
                        progress = value;
                        NotifyPropertyChanged("Progress");
                    }
                }
            }



            public List<FileRead> ReadPaths = new List<FileRead>();
            System.Windows.Threading.DispatcherTimer mReadTimer;
            public enum READSTATE
            {
                /// <summary>
                /// 闲置
                /// </summary>
                IDLE,
                /// <summary>
                /// 准备
                /// </summary>
                READY,
                /// <summary>
                /// 已经从服务器下载完毕，可以打开界面
                /// </summary>
                OK,
                /// <summary>
                /// 读取出错
                /// </summary>
                ERR
            }
            public READSTATE ReadState = READSTATE.IDLE;
            public delegate void StopHandler(ReadService sender);
            StopHandler StopEvent = null;
            public ReadService()
            {
                mReadTimer = new System.Windows.Threading.DispatcherTimer();
                mReadTimer.Interval = TimeSpan.FromSeconds(0.5);
                mReadTimer.Tick += new EventHandler(timer_Tick);
                ReadState = READSTATE.IDLE;
            }

            public void Start(List<string> paths, StopHandler stopfunc)
            {
                ReadPaths.Clear();
                foreach (string path in paths)
                {
                    ReadPaths.Add(new FileRead() { Path = path });
                }
                Progress = 0;
                ReadState = READSTATE.READY;
                mReadTimer.Start();
                StopEvent = stopfunc;
            }
            public void Touch(string path, FILEREAD_STATE state, int downloadSize, int size)
            {
                FileRead fr = ReadPaths.Find(f => f.Path == path);
                if (fr == null)
                    return;
                if (size > 0)
                {
                    fr.DownloadSize = downloadSize;
                    fr.Size = size;
                }
                fr.State = state;
                if (state == FILEREAD_STATE.READING)
                    return;

                //更新进度
                double cnt = ReadPaths.Count(f => f.State != FILEREAD_STATE.READING);
                Progress = 100 * cnt / ReadPaths.Count();
                if (cnt != ReadPaths.Count())
                    return;

                if (ReadPaths.All((f) => f.State == FILEREAD_STATE.OK))
                    ReadState = READSTATE.OK;
                else
                    ReadState = READSTATE.ERR;
            }
            public void Touch(string path, FILEREAD_STATE state)
            {
                Touch(path, state, 0, -1);
            }
            void timer_Tick(object sender, EventArgs e)
            {
                switch (ReadState)
                {
                    case READSTATE.OK:
                    case READSTATE.ERR:
                        mReadTimer.Stop();
                        if (StopEvent != null)
                            StopEvent.Invoke(this);
                        break;
                    case READSTATE.READY:
                        break;
                    case READSTATE.IDLE:
                        //异常，不应该出现
                        Stop();
                        break;
                }
            }
            public void Stop()
            {
                mReadTimer.Stop();
                StopEvent = null;
            }
            protected void NotifyPropertyChanged(string propertyName)
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
                }
            }
            public event PropertyChangedEventHandler PropertyChanged;
        }
        ReadService mReadService = new ReadService();
        /// <summary>
        /// 输出的路径
        /// </summary>
        string output_path = "";
        private void button_output_Click(object sender, RoutedEventArgs e)
        {
            if (listBox1.SelectedItems.Count == 0)
                return;
            mReadService.Stop();
            download_paths.Clear();
            System.Windows.Forms.FolderBrowserDialog fbd = new System.Windows.Forms.FolderBrowserDialog();

            if (fbd.ShowDialog() != System.Windows.Forms.DialogResult.OK)
                return;
            output_path = fbd.SelectedPath;

            for (int i = 0; i < listBox1.SelectedItems.Count; i++)
            {
                download_paths.Add((listBox1.SelectedItems[i] as FileProgress).FilePath);
            }

            if (mClient != null)//网络版
            {
                mReadService.Start(download_paths, new ReadService.StopHandler(mReadService_StopEventForOutput));

                GetDownloadFile(0);
            }
            else//本地版 
            {
                mRemoteHistoryService.GetRootPath(new FLY.Thick.RemoteHistory.GetRootPathReponseHandler(delegate(string rootpath, object state)
                {
                    var v = from s in download_paths select rootpath + @"\" + s;
                    Output(v);
                }), null);
            }
        }
        void Output(IEnumerable<string> paths)
        {
            //单纯合并就可以了

            //List<FlyData_ScanHistory> mDatas = new List<FlyData_ScanHistory>();
            //foreach (string path in paths)
            //{
            //    StreamReader sr = new StreamReader(path, Encoding.GetEncoding("GB2312"));
            //    string header = sr.ReadLine();
            //    while (!sr.EndOfStream)
            //    {
            //        string row = sr.ReadLine();
            //        FlyData_ScanHistory fd = new FlyData_ScanHistory();
            //        if (fd.TryParse(header, row))
            //        {
            //            mDatas.Add(fd);
            //        }
            //    }
            //    sr.Close();
            //}
            //mDatas.Sort((t1, t2) => t1.Time.CompareTo(t2.Time));

            string filename = ProductName + ".csv";
            string filepath = output_path + @"\" + filename;
            {
                StreamWriter sw = new StreamWriter(filepath, false, Encoding.GetEncoding("GB2312"));
                bool hasHeader = false;
                foreach (string path in paths)
                {
                    StreamReader sr = new StreamReader(path, Encoding.GetEncoding("GB2312"));
                    string header = sr.ReadLine();
                    if (!hasHeader)
                    {
                        sw.WriteLine(header);
                        hasHeader = true;
                    }
                    while (!sr.EndOfStream)
                    {
                        string row = sr.ReadLine();
                        sw.WriteLine(row);
                    }
                    sr.Close();
                }
                
                sw.Flush();
                sw.Close();
            }

            //完成
            MessageBox.Show("保存到路径 " + filepath, "输出到 .csv", MessageBoxButton.OK, MessageBoxImage.Information);
        }
        void mReadService_StopEventForOutput(ReadService sender)
        {
            switch (sender.ReadState)
            {
                case ReadService.READSTATE.OK:
                    {
                        var v = from rp in sender.ReadPaths select mClient.RootPath + rp.Path;
                        Output(v);
                    } break;
            }
        }
    }



    public interface IWindowHistoryReader
    {
        bool? ShowDialog(IEnumerable<string> paths, string productName);
    }
}
    

