using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Newtonsoft.Json;
using GatewayTool.Models;
using Newtonsoft.Json.Serialization;
using WjwLib.API.File;
using GatewayTool.Protocols;

namespace GatewayTool.UserControls
{
    public partial class UcDTUPanel : UserControl
    {
        private const string jsonFilter = "json(*.json)|*.json";
        private const string binFilter = "bin(*.bin)|*.bin";

        public event EventHandler<GridPropertyChangedArgs> ExecPropertyChanged;
        public event EventHandler ExecBindObjChanged;
        public event EventHandler ExecRefreshState;
        public event EventHandler ExecReadConfig;
        public event EventHandler<string> ExecDownloadConfig;
        public event EventHandler<int> ExecSelectTabIndexChanged;
        public event EventHandler<string> ExecUpgrade;

        private StringMsg _StrMsg;
        /// <summary>
        /// 字符串信息资源
        /// </summary>
        public StringMsg StrMsg
        {
            get => _StrMsg;
            set
            {
                _StrMsg = value;
                if (_StrMsg != null)
                {
                    InitStrings();
                }
            }
        }

        private DTU _BindDTU;
        /// <summary>
        /// 绑定的DTU
        /// </summary>
        public DTU BindDTU
        {
            get => _BindDTU;
            set => _BindDTU = value;
        }

        /// <summary>
        /// 设备图片
        /// </summary>
        public Image DeviceImage
        {
            get => picDTU.BackgroundImage;
            set
            {
                picDTU.BackgroundImage = value;
            }
        }

        /// <summary>
        /// 设备系统状态对象
        /// </summary>
        public Object DeviceSystemStateObj
        {
            get => gridDTU.SelectedObject;
            set
            {
                gridDTU.SelectedObject = value;
            }
        }

        /// <summary>
        /// 设备配置对象
        /// </summary>
        public Object DeviceConfigObj
        {
            get => gridConfig.SelectedObject;
            set
            {
                DTUConfig obj = value as DTUConfig;
                HandleDTUConfigObj(ref obj);
                gridConfig.SelectedObject = obj;
            }
        }

        /// <summary>
        /// 升级文件路径
        /// </summary>
        public string UpgradeFilePath 
        {
            get => this.txtFilePath.Text.Trim();
            set 
            {
                this.txtFilePath.Text = value;
                this.btnUpgrade.Enabled = !string.IsNullOrEmpty(value); //不为空时更新按钮才可用
            }
        }

        /// <summary>
        /// 固件升级进度
        /// </summary>
        public int UpgradeProgress
        {
            get => progressBar1.Value;
            set
            {
                if (value <= progressBar1.Maximum)
                {
                    progressBar1.Value = value;
                    lbProgressVal.Text = $"{value}%";
                }
            }
        }

        public UcDTUPanel(DTU dtu)
        {
            InitializeComponent();

            //this.tabDeviceManage.Parent = null;  //隐藏设备管理选项卡
            this.gbRestartDevice.Visible = false;  //隐藏重启设备区域
            this.gbModifyPassword.Visible = false; //隐藏修改密码区域

            this.Load += UcDTUPanel_Load;

            _BindDTU = dtu;
            this.DeviceImage = _BindDTU?.DeviceImage;
            this.DeviceSystemStateObj = _BindDTU?.SystemState;
            this.DeviceConfigObj = _BindDTU?.Config;

            this.UpgradeFilePath = _BindDTU?.UpgradeInfo.FirmwareFilePath;
            this.UpgradeProgress = _BindDTU == null ? 0 : _BindDTU.UpgradeInfo.UpgradeProgress;

            this.gridConfig.PropertyValueChanged += GridConfig_PropertyValueChanged;
            this.gridConfig.SelectedObjectsChanged += GridConfig_SelectedObjectsChanged;
        }

        private void UcDTUPanel_Load(object sender, EventArgs e)
        {
            InitStrings();
        }

        private void InitStrings()
        {
            this.tabSystemState.Text = _StrMsg.SystemState;
            this.gbDeviceImage.Text = _StrMsg.DeviceImage;
            this.gbStateInfo.Text = _StrMsg.StateInfo;
            this.btnRefreshState.Text = _StrMsg.Refresh;

            this.tabDeviceConfig.Text = _StrMsg.DeviceConfig;
            this.btnExport.Text = _StrMsg.Export;
            this.btnImport.Text = _StrMsg.Import;
            this.btnRead.Text = _StrMsg.Read;
            this.btnDownload.Text = _StrMsg.Write;

            this.tabDeviceManage.Text = _StrMsg.DeviceManage;
            this.gbUpgradeFirmware.Text = _StrMsg.UpgradeFirmware;
            this.lbChooseFile.Text = _StrMsg.ChooseFile;
            this.lbUpgradeProgress.Text = _StrMsg.UpgradeProgress;
            this.btnUpgrade.Text = _StrMsg.Upgrade;
            this.gbRestartDevice.Text = _StrMsg.RestartDevice;
            this.btnRestart.Text = _StrMsg.Restart;
            this.gbModifyPassword.Text = _StrMsg.ModifyPassword;
            this.lbNewPassword.Text = _StrMsg.NewPassword;
            this.lbConfirmNewPassword.Text = _StrMsg.ConfirmNewPassword;
            this.btnModify.Text = _StrMsg.Modify;
        }

        private void GridConfig_SelectedObjectsChanged(object sender, EventArgs e)
        {
            this.ExecBindObjChanged?.Invoke(sender, e);
        }

        private void GridConfig_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
        {
            this.ExecPropertyChanged?.Invoke(this, new GridPropertyChangedArgs() { Obj = s, Args = e });
        }

        private void tabControl1_DrawItem(object sender, DrawItemEventArgs e)
        {
            //Rectangle mainRec = tabControl1.ClientRectangle;
            //e.Graphics.FillRectangle(new SolidBrush(Color.White), mainRec);
            //for (int i = 0; i < tabControl1.TabPages.Count; i++)
            //{
            //    Rectangle rec = tabControl1.GetTabRect(i);
            //    if (tabControl1.SelectedTab == tabControl1.TabPages[i])
            //    {
            //        e.Graphics.FillRectangle(new SolidBrush(Color.DeepSkyBlue), rec);
            //        e.Graphics.DrawString(tabControl1.TabPages[i].Text, new Font("黑体", 12F, FontStyle.Bold), new SolidBrush(Color.White), rec, new StringFormat() { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center });
            //    }
            //    else
            //    {
            //        e.Graphics.FillRectangle(new SolidBrush(Color.White), rec);
            //        e.Graphics.DrawString(tabControl1.TabPages[i].Text, new Font("黑体", 12F, FontStyle.Bold), new SolidBrush(Color.Black), rec, new StringFormat() { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center });
            //    }
            //}
        }

        /// <summary>
        /// 浏览bin文件按钮单击
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnBrowse_Click(object sender, EventArgs e)
        {
            string filePath;
            string content = OpenBinFile(out filePath);
            if (filePath != null) //非取消操作时
            {
                txtFilePath.Text = filePath;
                this.btnUpgrade.Enabled = true;
            }
        }

        /// <summary>
        /// 更新按钮单击
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnUpgrade_Click(object sender, EventArgs e)
        {           
            ExecUpgrade?.Invoke(this, txtFilePath.Text.Trim());
        }

        /// <summary>
        /// 打开BIN文件得到路径，读取其中的二进制内容
        /// </summary>
        /// <param name="filePath">打开的文件路径</param>
        /// <returns>返回二进制数字符串</returns>       
        private string OpenBinFile(out string filePath)
        {
            filePath = string.Empty;
            string bin_str = "";
            byte[] binchar = new byte[] { };
            int file_len;

            //打开文件类
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.Title = _StrMsg.DialogOpen;
            //使用当前目录作为初始目录
            //dialog.InitialDirectory = System.AppDomain.CurrentDomain.BaseDirectory;
            //文件过滤，仅打开bin
            dialog.Filter = binFilter;
            //关闭选择多文件
            dialog.Multiselect = false;
            dialog.RestoreDirectory = true;
            DialogResult res = dialog.ShowDialog();
            if (res == DialogResult.OK)
            {
                //获取打开文件的完整路径
                filePath = dialog.FileName;
                //文件流类//用于文件的读写与关闭//来自于System.IO 
                FileStream fileStream = new FileStream(filePath, FileMode.Open);
                //读二进制文件类
                BinaryReader br = new BinaryReader(fileStream, Encoding.UTF8);
                //获取bin文件长度
                file_len = (int)fileStream.Length;
                //得到所有字节
                binchar = br.ReadBytes(file_len);
                //累加每字节数组转字符串
                bin_str = BitConverter.ToString(binchar);
                //关闭 BinaryReader 对象和基础流
                br.Close();
            }
            else if (res == DialogResult.Cancel)
            {
                filePath = null; //取消时置为null
            }

            //返回字符串
            return bin_str;
        }

        /// <summary>
        /// 导出按钮单击
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnExport_Click(object sender, EventArgs e)
        {
            string str = JsonConvert.SerializeObject(gridConfig.SelectedObject);
            SaveFileDialog saveFileDialog = new SaveFileDialog();
            saveFileDialog.Title = _StrMsg.DialogSaveAs;
            saveFileDialog.Filter = jsonFilter;
            saveFileDialog.DefaultExt = "*.json";
            //saveFileDialog.InitialDirectory = Environment.CurrentDirectory;
            saveFileDialog.RestoreDirectory = true;
            if (saveFileDialog.ShowDialog() == DialogResult.OK)
            {
                bool res = PlainText.WriteFileContent(saveFileDialog.FileName, str);
                if (res)
                {
                    MessageBox.Show(_StrMsg.ExportSuccess, _StrMsg.Prompt, MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                else
                {
                    MessageBox.Show(_StrMsg.ExportFail, _StrMsg.Error, MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }

        /// <summary>
        /// 导入按钮单击
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnImport_Click(object sender, EventArgs e)
        {
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.Title = _StrMsg.DialogOpen;
            dialog.Filter = jsonFilter;
            dialog.Multiselect = false;
            dialog.RestoreDirectory = true;
            if (dialog.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    string str = PlainText.GetFileContent(dialog.FileName);
                    DTUConfig obj = JsonConvert.DeserializeObject<DTUConfig>(str);
                    if (obj == null)
                    {
                        MessageBox.Show(_StrMsg.ImportFail, _StrMsg.Error, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                    else
                    {
                        DTUConfig rawConfig = (DTUConfig)gridConfig.SelectedObject; //原始配置对象
                        obj.DeviceId = rawConfig.DeviceId; //获取原始网关设备ID，防止被导入值修改
                        if (HandleDTUConfigObj(ref obj))
                        {
                            MessageBox.Show(_StrMsg.ImportSuccess, _StrMsg.Prompt, MessageBoxButtons.OK, MessageBoxIcon.Information);
                        }
                    }
                    gridConfig.SelectedObject = obj;
                }
                catch
                {
                    gridConfig.SelectedObject = new DTUConfig();
                    MessageBox.Show(_StrMsg.ParseFail, _StrMsg.Error, MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }

        /// <summary>
        /// 处理DTU配置对象及其子对象
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        private bool HandleDTUConfigObj(ref DTUConfig obj) 
        {
            if (obj == null) return false;
            SensorDataItemCollection sensorCollection = new SensorDataItemCollection();
            foreach (var item in obj.SensorData)
            {
                string itemStr = item.ToString();
                SensorDataItem dataItem = JsonConvert.DeserializeObject<SensorDataItem>(itemStr);
                if (dataItem != null)
                {
                    sensorCollection.Add(dataItem);
                }
            }
            obj.SensorData = sensorCollection;

            CommandDataItemCollection commandCollection = new CommandDataItemCollection();
            foreach (var item in obj.CommandData)
            {
                string itemStr = item.ToString();
                CommandDataItem dataItem = JsonConvert.DeserializeObject<CommandDataItem>(itemStr);
                if (dataItem != null)
                {
                    commandCollection.Add(dataItem);
                }
            }
            obj.CommandData = commandCollection;
            return true;
        }

        /// <summary>
        /// 下发按钮单击
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnDownload_Click(object sender, EventArgs e)
        {
            if (gridConfig.SelectedObject == null)
            {
                ExecDownloadConfig?.Invoke(this, null);
            }
            else
            {
                DTUConfig config = (DTUConfig)gridConfig.SelectedObject;
                for (int i = config.CommandData.Count - 1; i >= 0; i--)
                {
                    if (!config.CommandData[i].Validate())
                    {
                        MessageBox.Show($"CommandDataItem{i}中存在非法数值", "数据非法", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        return;
                    }
                }

                string str = JsonConvert.SerializeObject(gridConfig.SelectedObject);
                str += $"+QFDWL: {str.Length},{XorSum16.CheckSum(str)}";
                MessageBox.Show(WjwLib.API.System.JsonHelper.ConvertJsonString(str));
                ExecDownloadConfig?.Invoke(this, str);
            }
        }      

        /// <summary>
        /// 选项卡切换事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
        {
            ExecSelectTabIndexChanged?.Invoke(this, tabControl1.SelectedIndex);
        }

        /// <summary>
        /// 刷新按钮单击
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnRefreshState_Click(object sender, EventArgs e)
        {
            ExecRefreshState?.Invoke(this, e);
        }

        /// <summary>
        /// 读取按钮单击
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnRead_Click(object sender, EventArgs e)
        {
            ExecReadConfig?.Invoke(this, e);
        }
    }

    /// <summary>
    /// 表格属性更改参数
    /// </summary>
    public class GridPropertyChangedArgs
    {
        /// <summary>
        /// 表格实例
        /// </summary>
        public object Obj { get; set; }

        /// <summary>
        /// 属性值更改事件参数
        /// </summary>
        public PropertyValueChangedEventArgs Args { get; set; }
    }
}