using CommonLibrary;
using HslCommunication;
using HslCommunication.BasicFramework;
using HslCommunication.Enthernet;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading.Tasks;
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.Navigation;
using System.Windows.Shapes;
using ClientsLibrary;
using System.Threading;
using 软件系统客户端Wpf.Views;
using System.Windows.Media.Animation;
using MaterialDesignThemes.Wpf;

namespace 软件系统客户端Wpf
{






    /***************************************************************************************
     * 
     *    模版日期    2017-07-11
     *    创建人      胡少林
     *    版权所有    胡少林
     *    授权说明    模版仅授权个人使用，如需商用，请联系hsl200909@163.com洽谈
     *    说明一      JSON组件引用自james newton-king，遵循MIT授权协议
     *    说明二      主题及各种主件来自:https://github.com/ButchersBoy/MaterialDesignInXamlToolkit
     * 
     ****************************************************************************************/

    /***************************************************************************************
     * 
     *    版本说明    最新版以github为准，由于提交更改比较频繁，需要经常查看官网地址:https://github.com/dathlin/C-S-
     *    注意        本代码的相关操作未作密码验证，如有需要，请自行完成
     *    如果        遇到启动调试就退出了，请注释掉App.xaml.cs文件中的指允许启动一个实例的代码
     *    
     **************************************************************************************************/





    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }


        #region 窗口相关方法
        /// <summary>
        /// 指示窗口是否显示的标志
        /// </summary>
        private bool IsWindowShow { get; set; } = false;

        private void Window_Activated(object sender, EventArgs e)
        {
            //窗口激活就触发，不应把初始代码放这里
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            IsWindowShow = false;

            //通知服务器退出网络服务
            net_socket_client.ClientClose();

            //保存当前的颜色选择
            var p = new PaletteHelper().QueryPalette();
            using (StreamWriter sw = new StreamWriter(AppDomain.CurrentDomain.BaseDirectory + @"Palette.txt", false, Encoding.UTF8))
            {
                sw.Write(JObject.FromObject(p).ToString());
            }
            //等待一秒退出
            using (FormWaitInfomation fwm = new FormWaitInfomation("正在退出程序...", 1000))
            {
                fwm.ShowDialog();
            }
        }

        private void Window_ContentRendered(object sender, EventArgs e)
        {
            //窗口呈现完成触发，已经显示了
            //窗口显示
            IsWindowShow = true;

            //udp测试
            //SendServerUdpData(0, "显示了窗体");

            //是否显示更新日志，显示前进行判断该版本是否已经显示过了
            if (UserClient.JsonSettings.IsNewVersionRunning)
            {
                UserClient.JsonSettings.IsNewVersionRunning = false;
                UserClient.JsonSettings.SaveToFile();
                MenuItem更新日志_Click(null, new RoutedEventArgs());
            }

            //根据权限使能菜单
            if (UserClient.UserAccount.Grade < AccountGrade.SuperAdministrator)
            {
                MenuItem日志查看.IsEnabled = false;
                MenuItem账户管理.IsEnabled = false;
                MenuItem远程更新.IsEnabled = false;
                MenuItem注册账户.IsEnabled = false;
                MenuItem消息发送.IsEnabled = false;
                MenuItem开发中心.IsEnabled = false;
                MenuItem分厂配置.IsEnabled = false;
            }


            //启动网络服务
            Net_Socket_Client_Initialization();
            //启动定时器
            TimeTickInitilization();
            //显示头像
            SoftUserPortraitInitialization();
            SoftUserPortrait.DownloadUserPortraint();
            AccountChip.Content = UserClient.UserAccount.UserName;

            SetShowRenderControl(UIControl_Home);
        }

        private void Window_Initialized(object sender, EventArgs e)
        {
            //在窗口实例化之后触发
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            //在窗体加载时触发，窗体还不显示任何东西
            //窗口载入
            Account_grade.Text = AccountGrade.GetDescription(UserClient.UserAccount.Grade);
            Account_factory.Text = UserClient.UserAccount.Factory;
            Account_register.Text = UserClient.UserAccount.RegisterTime.ToString();
            Account_last.Text = UserClient.UserAccount.LastLoginTime.ToString();
            Account_times.Text = UserClient.UserAccount.LoginFrequency.ToString();
            Account_address.Text = UserClient.UserAccount.LastLoginIpAddress;

            //状态栏设置
            TextBlock_CopyRight.Text = $"本软件著作权归{Resource.StringResouce.SoftCopyRight}所有";

            //绑定事件，仅执行一次，不能放到show方法里
            net_socket_client.MessageAlerts += Net_socket_client_MessageAlerts;
            net_socket_client.LoginFailed += Net_socket_client_LoginFailed;
            net_socket_client.LoginSuccess += Net_socket_client_LoginSuccess;
            net_socket_client.AcceptByte += Net_socket_client_AcceptByte;
            net_socket_client.AcceptString += Net_socket_client_AcceptString;

            TextBlock_Announcement.Text = UserClient.Announcement;

            TextBlock_Version.Text = UserClient.CurrentVersion.ToString();

            //初始化窗口
            MainRenderInitialization();

            //加载主题
            new PaletteHelper().SetLightDark(UserClient.JsonSettings.IsThemeDark);
        }

        private void AddStringRenderShow(string str)
        {
            var messageQueue = SoftSnackbar.MessageQueue;
            //the message queue can be called from any thread
            Task.Factory.StartNew(() => SoftSnackbar.MessageQueue.Enqueue(str));
        }

        #endregion


        #region 菜单逻辑块


        private void MenuItem公告管理_Click(object sender, RoutedEventArgs e)
        {
            using (FormInputAndAction fiaa = new FormInputAndAction(str => UserClient.Net_simplify_client.ReadFromServer(
                 CommonHeadCode.SimplifyHeadCode.更新公告, str).IsSuccess, UserClient.Announcement, "请输入公告内容"))
            {
                fiaa.ShowDialog();
            }
        }

        private void MenuItem账户管理_Click(object sender, RoutedEventArgs e)
        {
            FormAccountManage fam = new FormAccountManage(() =>
            {
                OperateResultString result = UserClient.Net_simplify_client.ReadFromServer(CommonHeadCode.SimplifyHeadCode.获取账户);
                if (result.IsSuccess) return result.Content;
                else return result.ToMessageShowString();
            }, m => UserClient.Net_simplify_client.ReadFromServer(CommonHeadCode.SimplifyHeadCode.更细账户, m).IsSuccess);
            fam.ShowDialog();
            fam.Dispose();
        }

        private void MenuItem注册账户_Click(object sender, RoutedEventArgs e)
        {
            using (FormRegisterAccount fra = new FormRegisterAccount(UserClient.SystemFactories.ToArray()))
            {
                fra.ShowDialog();
            }
        }

        private void MenuItem日志查看_Click(object sender, RoutedEventArgs e)
        {
            using (FormLogView flg = new FormLogView())
            {
                flg.ShowDialog();
            }
        }

        private void MenuItem远程更新_Click(object sender, RoutedEventArgs e)
        {
            if (UserClient.UserAccount.UserName == "admin")
            {
                using (FormUpdateRemote fur = new FormUpdateRemote())
                {
                    fur.ShowDialog();
                }
            }
            else
            {
                MessageBox.Show("权限不足！");
            }
        }

        private void MenuItem消息发送_Click(object sender, RoutedEventArgs e)
        {
            using (FormInputAndAction fiaa = new FormInputAndAction(str => UserClient.Net_simplify_client.ReadFromServer(
                 CommonHeadCode.SimplifyHeadCode.群发消息, UserClient.UserAccount.UserName + ":" + str).IsSuccess, "", "请输入群发的消息："))
            {
                fiaa.ShowDialog();
            }
        }

        private void MenuItem开发中心_Click(object sender, RoutedEventArgs e)
        {
            using (FormSuper fs = new FormSuper(() =>
            {
                OperateResultBytes result = UserClient.Net_simplify_client.ReadFromServer(CommonHeadCode.SimplifyHeadCode.性能计数, new byte[0]);
                //解析
                if (result.IsSuccess)
                {
                    int[] data = new int[result.Content.Length / 4];
                    for (int i = 0; i < data.Length; i++)
                    {
                        data[i] = BitConverter.ToInt32(result.Content, i * 4);
                    }
                    return data;
                }
                else
                {
                    return null;
                }

            }))
            {
                fs.ShowDialog();
            }
        }

        private void MenuItem密码更改_Click(object sender, RoutedEventArgs e)
        {
            using (FormPasswordModify fpm = new FormPasswordModify(UserClient.UserAccount.Password,
                p =>
                {
                    JObject json = new JObject
                    {
                        { UserAccount.UserNameText, UserClient.UserAccount.UserName },
                        { UserAccount.PasswordText, p }
                    };
                    return UserClient.Net_simplify_client.ReadFromServer(CommonHeadCode.SimplifyHeadCode.密码修改, json.ToString()).IsSuccess;
                }, 6, 8))
            {
                fpm.ShowDialog();
            }
        }
        
        private void MenuItem聊天信息_Click(object sender, RoutedEventArgs e)
        {
            //var messageQueue = SoftSnackbar.MessageQueue;
            //var message = "这是一条测试数据这是一条测试数据这是一条测试数据这是一条测试数据这是一条测试数据" + index++;

            ////the message queue can be called from any thread
            //Task.Factory.StartNew(() => messageQueue.Enqueue(message));

            SetShowRenderControl(UIControls_Chat);
            UIControls_Chat.ScrollToDown();
        }

        private void MenuItem头像更改_Click(object sender, RoutedEventArgs e)
        {
            SoftUserPortrait.ChangePortrait();
        }


        private void MenuItem主题色调_Click(object sender, RoutedEventArgs e)
        {
            SetShowRenderControl(UIControl_Palette);
        }

        private void MenuItem关于本软件_Click(object sender, RoutedEventArgs e)
        {
            using (FormAbout fa = new FormAbout(Resource.StringResouce.SoftName,
                UserClient.CurrentVersion, 2017, Resource.StringResouce.SoftCopyRight))
            {
                fa.ShowDialog();
            }
        }

        private void MenuItem更新日志_Click(object sender, RoutedEventArgs e)
        {
            //更新情况复位
            if (UserClient.JsonSettings.IsNewVersionRunning)
            {
                UserClient.JsonSettings.IsNewVersionRunning = false;
                UserClient.JsonSettings.SaveToFile();
            }
            using (FormUpdateLog ful = new FormUpdateLog(UserClient.HistoryVersions))
            {
                ful.ShowDialog();
            }
        }

        private void MenuItem版本号说明_Click(object sender, RoutedEventArgs e)
        {
            using (FormAboutVersion fav = new FormAboutVersion(UserClient.CurrentVersion))
            {
                fav.ShowDialog();
            }
        }

        private void MenuItem意见反馈_Click(object sender, RoutedEventArgs e)
        {
            using (FormInputAndAction fiaa = new FormInputAndAction(str => UserClient.Net_simplify_client.ReadFromServer(
                 CommonHeadCode.SimplifyHeadCode.意见反馈, UserClient.UserAccount.UserName + ":" + str).IsSuccess, "", "请输入意见反馈："))
            {
                fiaa.ShowDialog();
            }
        }

        private void Button_Quit_Click(object sender, RoutedEventArgs e)
        {
            App.QuitCode = 1;
            Close();
        }


        private void Border_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            //点击了文件查看
            SetShowRenderControl(UIControl_Files);
            UIControl_Files.UpdateFiles();
        }


        private void MenuItem分厂配置_Click(object sender, RoutedEventArgs e)
        {
            using (FormInputAndAction fiaa = new FormInputAndAction(
            str => UserClient.Net_simplify_client.ReadFromServer(
                CommonHeadCode.SimplifyHeadCode.上传分厂, str).IsSuccess,
            JArray.FromObject(UserClient.SystemFactories).ToString(),
            "请按照JSON格式更新分厂信息，然后提交："))
            {
                fiaa.ShowDialog();
            }
        }

        #endregion


        #region 异步网络块

        private NetComplexClient net_socket_client = new NetComplexClient();

        private void Net_Socket_Client_Initialization()
        {
            try
            {
                net_socket_client.KeyToken = CommonHeadCode.KeyToken;//新增的身份令牌
                net_socket_client.EndPointServer = new System.Net.IPEndPoint(
                    System.Net.IPAddress.Parse(UserClient.ServerIp),
                    CommonLibrary.CommonLibrary.Port_Main_Net);
                net_socket_client.ClientAlias = $"{UserClient.UserAccount.UserName} ({UserClient.UserAccount.Factory})";//标记客户端在线的名称
                net_socket_client.ClientStart();
            }
            catch (Exception ex)
            {
                SoftBasic.ShowExceptionMessage(ex);
            }
        }
        /// <summary>
        /// 接收到服务器的字节数据的回调方法
        /// </summary>
        /// <param name="state">网络连接对象</param>
        /// <param name="customer">用户自定义的指令头，用来区分数据用途</param>
        /// <param name="data">数据</param>
        private void Net_socket_client_AcceptString(AsyncStateOne state, int customer, string data)
        {
            if (customer == CommonHeadCode.MultiNetHeadCode.弹窗新消息)
            {
                if(IsWindowShow) Dispatcher.Invoke(new Action(() =>
                {
                    FormPopup fpp = new FormPopup(data, System.Drawing.Color.DodgerBlue, 10000);
                    fpp.Show();
                }));
            }
            else if (customer == CommonHeadCode.MultiNetHeadCode.总在线信息)
            {
                if (IsWindowShow) Dispatcher.Invoke(new Action(() =>
                {
                    ListBox_Onlines.ItemsSource = data.Split('#');
                }));
            }
            else if (customer == CommonHeadCode.MultiNetHeadCode.关闭客户端)
            {
                if (IsWindowShow) Dispatcher.Invoke(new Action(() =>
                {
                    Close();
                }));
            }
            else if (customer == CommonHeadCode.SimplifyHeadCode.更新公告)
            {
                //此处应用到了同步类的指令头
                if (IsWindowShow) Dispatcher.Invoke(new Action(() =>
                {
                    UserClient.Announcement = data;
                    TextBlock_Announcement.Text = data;
                    FormPopup fpp = new FormPopup(data, System.Drawing.Color.DodgerBlue, 10000);
                    fpp.Show();
                }));
            }
            else if (customer == CommonHeadCode.MultiNetHeadCode.初始化数据)
            {
                //收到服务器的数据
                JObject json = JObject.Parse(data);
                UserClient.DateTimeServer = json["Time"].ToObject<DateTime>();
                List<string> chats = JArray.Parse(json["chats"].ToString()).ToObject<List<string>>();
                StringBuilder sb = new StringBuilder();
                chats.ForEach(m => { sb.Append(m + Environment.NewLine); });
                if (IsWindowShow) Dispatcher.Invoke(new Action(() =>
                {
                    TextBlock_ServerTime.Text = UserClient.DateTimeServer.ToString("yyyy-MM-dd HH:mm:ss");
                    TextBlock_FileCount.Text = json["FileCount"].ToObject<int>().ToString();
                    UIControls_Chat.AddChatsHistory(sb.ToString());
                }));
            }
            else if (customer == CommonHeadCode.MultiNetHeadCode.文件总数量)
            {
                if (IsWindowShow) Dispatcher.Invoke(new Action(() =>
                {
                    TextBlock_FileCount.Text = data;
                }));
            }
            else if (customer == CommonHeadCode.MultiNetHeadCode.留言版消息)
            {
                if (IsWindowShow) Dispatcher.Invoke(new Action(() =>
                {
                    UIControls_Chat?.DealwithReceive(data);
                }));
            }
        }

        private void Net_socket_client_AcceptByte(AsyncStateOne object1, int customer, byte[] object2)
        {
            //接收到服务器发来的字节数据
            if (IsWindowShow) Dispatcher.Invoke(new Action(() =>
            {
                MessageBox.Show(customer.ToString());
            }));
        }

        private void Net_socket_client_LoginSuccess()
        {
            //登录成功，或重新登录成功的事件，有些数据的初始化可以放在此处
            if (IsWindowShow) Dispatcher.Invoke(new Action(() =>
            {
                TextBlock_ClientStatus.Text = "客户端启动成功";
            }));
        }

        private void Net_socket_client_LoginFailed(int object1)
        {
            //登录失败的情况，如果连续三次连接失败，请考虑退出系统
            if (object1 > 3)
            {
                if (IsWindowShow) Dispatcher.Invoke(new Action(() =>
                {
                    Close();
                }));
            }
        }

        private void Net_socket_client_MessageAlerts(string object1)
        {
            //信息提示
            if (IsWindowShow) Dispatcher.Invoke(new Action(() =>
            {
                TextBlock_ClientStatus.Text = object1;
            }));
        }











        #endregion


        #region 后台计数线程

        /*********************************************************************************************
         * 
         *    说明       一个后台线程，用来执行一些周期执行的东西
         *    注意       它不仅执行每秒触发的代码，也支持每分钟，每天，每月，每年等等
         * 
         ********************************************************************************************/


        /// <summary>
        /// 初始化后台的计数线程
        /// </summary>
        public void TimeTickInitilization()
        {

            Thread thread = new Thread(new ThreadStart(ThreadTimeTick));
            thread.IsBackground = true;
            thread.Start();
        }

        public void ThreadTimeTick()
        {
            Thread.Sleep(300);//加一个微小的延时
            int second = DateTime.Now.Second - 1;
            int minute = -1;
            int hour = -1;
            int day = -1;
            Action DTimeShow = delegate
            {
                //显示服务器的时间和当前网络的延时时间，通常为毫秒
                TextBlock_ServerTime.Text = net_socket_client.ServerTime.ToString("yyyy-MM-dd HH:mm:ss");
                TextBlock_ServerDelay.Text = net_socket_client.DelayTime.ToString();
            };

            while (IsWindowShow)
            {
                while (DateTime.Now.Second == second)
                {
                    Thread.Sleep(20);
                }
                second = DateTime.Now.Second;
                if (IsWindowShow) Dispatcher.Invoke(DTimeShow);
                //每秒钟执行的代码
                UserClient.DateTimeServer = net_socket_client.ServerTime;

                if (second == 0)
                {
                    //每个0秒执行的代码
                }
                if (minute != DateTime.Now.Minute)
                {
                    minute = DateTime.Now.Minute;
                    //每分钟执行的代码
                }
                if (hour != DateTime.Now.Hour)
                {
                    hour = DateTime.Now.Hour;
                    //每小时执行的代码
                }
                if (day != DateTime.Now.Day)
                {
                    day = DateTime.Now.Day;
                    //每天执行的代码
                }
            }
        }




        #endregion

        #region Udp发送示例
        /// <summary>
        /// 调用该方法并指定参数即可，最长字符串不得
        /// </summary>
        /// <param name="data"></param>
        private void SendServerUdpData(int customer, string data)
        {
            //测试发送udp消息
            UserClient.Net_Udp_Client.SendMessage(customer, data);
        }

        #endregion

        #region 头像图片上传下载块


        private UserPortrait SoftUserPortrait { get; set; }

        private void SoftUserPortraitInitialization()
        {
            SoftUserPortrait = new UserPortrait(AppDomain.CurrentDomain.BaseDirectory + @"Portrait\" + UserClient.UserAccount.UserName, 
                m => {
                    byte[] content = System.IO.File.ReadAllBytes(m);
                    BitmapImage bi = new BitmapImage();
                    bi.BeginInit();
                    bi.StreamSource = new System.IO.MemoryStream(content);
                    bi.EndInit();
                    AccountPortrait.Source = bi;
                },
                ()=>
                {
                    AccountPortrait.Source = null;
                });
        }

        
        private void AccountChip_Click(object sender, RoutedEventArgs e)
        {
            //点击了头像，请求下载高清版本头像
            using (FormMatterRemind fmr = new FormMatterRemind("正在下载图片", SoftUserPortrait.ThreadPoolDownloadSizeLarge))
            {
                fmr.ShowDialog();
            }
        }


        #endregion

        #region 多界面管理块

        private List<UserControl> all_main_render = new List<UserControl>();


        private UserChat UIControls_Chat { get; set; }

        private UserHome UIControl_Home { get; set; }
        
        private UserFileRender UIControl_Files { get; set; }

        private UserPaletteSelector UIControl_Palette { get; set; }

        /// <summary>
        /// 正在显示的子界面
        /// </summary>
        private UserControl CurrentRender { get; set; }

        /// <summary>
        /// 主界面的初始化
        /// </summary>
        private void MainRenderInitialization()
        {
            //将所有的子集控件添加进去

            /*******************************************************************************
             * 
             *    例如此处展示了文件控件是如何添加进去的 
             *    1.先进行实例化，赋值初始参数
             *    2.添加进项目
             *    3.显示
             *
             *******************************************************************************/

            //UIControls_Files = new UIControls.ShareFilesRender()
            //{
            //    Visible = false,
            //    Parent = panel_main,//决定了放在哪个界面显示，此处示例
            //    Dock = DockStyle.Fill,
            //};
            //all_main_render.Add(UIControls_Files);

            UIControls_Chat = new UserChat((m) =>
            {
                net_socket_client.Send(CommonHeadCode.MultiNetHeadCode.留言版消息, m);
            });
            all_main_render.Add(UIControls_Chat);

            UIControl_Home = new UserHome();
            all_main_render.Add(UIControl_Home);

            UIControl_Palette = new UserPaletteSelector() { DataContext = new PaletteSelectorViewModel() };
            all_main_render.Add(UIControl_Palette);

            UIControl_Files = new UserFileRender();
            all_main_render.Add(UIControl_Files);

        }

        private void SetShowRenderControl(UserControl control)
        {
            if (!ReferenceEquals(CurrentRender, control))
            {
                CurrentRender = control;
                //UserContentControl.Content = control;

                DoubleAnimation d_opacity = new DoubleAnimation(1, 0, TimeSpan.FromMilliseconds(100));
                DoubleAnimation d_y = new DoubleAnimation(0, -10, TimeSpan.FromMilliseconds(100));
                TranslateTransform tt = new TranslateTransform();
                UserContentControl.RenderTransform = tt;
                d_opacity.Completed += delegate
                {
                    UserContentControl.Content = control;
                    DoubleAnimation d_opacity2 = new DoubleAnimation(0, 1, TimeSpan.FromMilliseconds(100));
                    DoubleAnimation d_y2 = new DoubleAnimation(10, 0, TimeSpan.FromMilliseconds(100));
                    TranslateTransform tt2 = new TranslateTransform();
                    UserContentControl.RenderTransform = tt2;
                    tt2.BeginAnimation(TranslateTransform.XProperty, d_y2);
                    UserContentControl.BeginAnimation(OpacityProperty, d_opacity2);
                };

                UserContentControl.BeginAnimation(OpacityProperty, d_opacity);
                tt.BeginAnimation(TranslateTransform.XProperty, d_y);
            }
        }




        private void SetShowRenderControl(Type typeControl)
        {
            UserControl control = null;
            foreach (var c in all_main_render)
            {
                if (c.GetType() == typeControl)
                {
                    control = c;
                    break;
                }
            }
            if (control != null) SetShowRenderControl(control);
        }

        #endregion

        private void Button_BackMain_Click(object sender, RoutedEventArgs e)
        {
            //点击了主页
            SetShowRenderControl(UIControl_Home);
        }
        
        private async void Button_Dialog_Click(object sender, RoutedEventArgs e)
        {
            //点击了显示一个提示的窗体
            DialogHostWait.IsOpen = true;
            await Task.Delay(2000);
            DialogHostWait.IsOpen = false;
        }


    }
}
