using Kivii.Client.SamplePackages.Entities;
using Kivii.Linq;
using Kivii.Samples.Entities;
using Kivii.Samples.Transforms;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Timers;
using System.Windows.Forms;

namespace Kivii.Client.SamplePackages
{
    public partial class FrmMain : Form
    {
        #region 私有变量
        private JsonServiceClient _client;
        private Location _currentLocation;
        private Sample _currentPackage;
        private List<Sample> _currentSamples;
        private AuthenticateResponse _userInfo;
        internal static Reader ReaderInstance { get; set; }
        System.Timers.Timer _tmr = null;//定时器
        #endregion
        public FrmMain()
        {
            InitializeComponent();
        }

        private void FrmMain_Load(object sender, EventArgs e)
        {

            initControls();
            loadDefault(tbxServiceUrl, tbxUserName, tbxPassword);
            //initReader();
        }

        #region 界面控件默认值及控制
        private void initReader()
        {
            ReaderInstance = new Reader();

            //加载事件
            ReaderInstance.Connected += new EventHandler<ConnectionChangedEventArgs>(reader_Connected);
            ReaderInstance.ConnectionLost += reader_ConnectionLost;
            //ReaderInstance.Disconnected += reader_Disconnected;
        }

        private void initControls()
        {
            dgvSamples.AutoGenerateColumns = false;
            tbxServiceUrl.Enabled = true;
            tbxUserName.Enabled = true;
            tbxPassword.Enabled = true;
            tbSetCurrentPackage.Enabled = false;
            cbSetCurrentPackageNode.Enabled = false;
            btnLogin.Enabled = true;
            btnLogout.Enabled = false;
            btnScanRfid.Enabled = false;
            tbScanSample.Enabled = false;
            tbScanSample.Text = "";
            btnClearCurrentPackage.Enabled = false;
            tbCurrentLocation.Text = "";
            tbCurrentDepartment.Text = "";
            tbCurrentPackage.Text = "";
            tbCurrentPackageNode.Text = "";
            tbSetCurrentPackage.Text = "";
            cbSetCurrentPackageNode.SelectedItem = null;
            _currentSamples = null;
            dgvSamples.DataSource = null;
        }

        private void loadDefault(params Control[] ctls)
        {
            try
            {
                using (var conn = KiviiContext.GetOpenedDbConnection<UiSetting>())
                {
                    foreach (var ctl in ctls)
                    {
                        //UiSetting setting = null;
                        var setting = conn.Select<UiSetting>(o => o.FormName == this.Name && o.ControlName == ctl.Name).FirstOrDefault();
                        if (setting == null)
                        {
                            if (ctl.Name == tbxServiceUrl.Name) ctl.Text = Configs.DefaultBaseUrl;
                            continue;
                        }
                        ctl.Text = setting.ControlValue;
                    }
                }
            }
            catch
            {

            }
        }

        private void setDefault(params Control[] ctls)
        {
            try
            {
                using (var conn = KiviiContext.GetOpenedDbConnection<UiSetting>())
                {
                    foreach (var ctl in ctls)
                    {
                        var setting = conn.Select<UiSetting>(o => o.FormName == this.Name && o.ControlName == ctl.Name).FirstOrDefault();
                        if (setting == null)
                        {
                            setting = new UiSetting();
                            setting.FormName = this.Name;
                            setting.ControlName = ctl.Name;
                            setting.ControlValue = ctl.Text;
                            conn.Insert(setting);
                        }
                        else
                        {
                            setting.ControlValue = ctl.Text;
                            conn.Update(setting);
                        }
                    }
                }
            }
            catch
            {

            }
        }
        #endregion

        #region 业务方法
        private void initUserInfo(AuthenticateResponse response = null)
        {
            if (response == null)
            {
                _userInfo = null;
                _currentLocation = null;
                _currentPackage = null;
                return;
            }
            _userInfo = new AuthenticateResponse();
            _userInfo.PopulateWith(response);
            tbCurrentDepartment.Text = _userInfo.DepartmentName;
            initLocation();
        }

        private void initLocation()
        {
            if (_client == null)
            {
                MessageBox.Show("请先登录!");
                return;
            }
            if (_userInfo == null)
            {
                MessageBox.Show("未取得登录人信息,请重新登录!");
                return;
            }
            var request = new LocationQuery();
            request.OwnerKvid = _userInfo.DepartmentKvid;
            //request.OwnerKvid = Guid.Parse("D4CE47D2-5FC8-479D-A0CA-BACDF1A891BF");//色牢度组
            //request.OwnerKvid = Guid.Parse("9D026818-6E78-40F8-A715-2887F96F34DC");//纤检组
            //request.OwnerKvid = Guid.Parse("208C24FB-1443-4B9E-9886-02ED3B9A8F45");//安全组
            //request.OwnerKvid = Guid.Parse("7CF9CF7B-19F5-4A1A-A94C-5BC21EA8ED76");//纤维含量组
            //request.OwnerKvid = Guid.Parse("BB355D5A-9D4E-4337-B577-7BB7A1625F68");//羽绒组
            try
            {
                var resp = _client.Post(request);
                if (resp.Results.Count <= 0)
                {
                    MessageBox.Show("未找到当前登录人所在组及位置信息!", "位置信息");
                    return;
                }
                var location = resp.Results.FirstOrDefault();
                _currentLocation = new Location();
                _currentLocation.PopulateWith(location);
                tbSetCurrentPackage.Enabled = _currentLocation != null;
                tbCurrentLocation.Text = _currentLocation.Address;
            }
            catch (Exception ex)
            {
                _currentLocation = null;
                tbSetCurrentPackage.Enabled = _currentLocation != null;
                MessageBox.Show(ex.GetResponseStatus().Message, ex.Message);
            }
        }

        private void querySampleInPackaged()
        {
            if (_client == null)
            {
                MessageBox.Show("请先登录!");
                return;
            }
            if (_currentPackage == null)
            {
                MessageBox.Show("请先设置箱号!");
                return;
            }
            this.Invoke(new Action(delegate
            {
                dgvSamples.DataSource = null;
            }));
            var request = new SampleQuery2();
            request.PackageKvid = _currentPackage.Kvid;
            var task = _client.PostAsync(request);
            task.Success(resp =>
            {
                _currentSamples = resp.Results.ToList();
                this.Invoke(new Action(delegate
                {
                    dgvSamples.DataSource = _currentSamples;
                }));
            });
            task.Error(err =>
            {
                MessageBox.Show(err.Message, "查询样品");
            });
        }

        private void samplePrepackaging(string tid, string epc = null, string bizId = null)
        {
            if (tid.IsNullOrEmpty() && bizId.IsNullOrEmpty() && epc.IsNullOrEmpty()) return;
            var request = new SamplePrePackaging();
            if (!tid.IsNullOrEmpty()) request.Tid = tid;
            Guid epcKvid = Guid.Empty;
            if (Guid.TryParse(epc, out epcKvid))
            {
                //return;
                request.BizKvid = epcKvid;
            }
            if (!bizId.IsNullOrEmpty()) request.BizId = bizId;
            request.OwnerKvid = _currentLocation.OwnerKvid;
            try
            {
                var resp = _client.Post(request);
                if (resp.Results.Count <= 0)
                {
                    MessageBox.Show("未找到样品,样品可能未涉及到当前组!", "Rfid读取样品");
                    return;
                }
                var record = resp.Results[0];
                samplePackaging(record);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.GetResponseStatus().Message, "Rfid读取样品");
            }
        }

        private void samplePackaging(Sample sample)
        {
            if (sample == null) return;
            var request = new SamplePackaging();
            request.Package = _currentPackage;
            request.Kvid = sample.Kvid;
            request.Location = _currentLocation;
            //var task = _client.PostAsync(request);
            try
            {
                var resp = _client.Post(request);
                if (resp.Results.Count <= 0)
                {
                    return;
                }
                var record = resp.Results[0];
                if (_currentSamples == null) _currentSamples = new List<Sample>();
                if (!_currentSamples.Exists(o => o.Kvid == record.Kvid))
                {
                    _currentSamples.Add(record);
                }
                this.Invoke(new Action(delegate
                {
                    dgvSamples.DataSource = null;
                }));
                this.Invoke(new Action(delegate
                {
                    dgvSamples.DataSource = _currentSamples;
                }));
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.GetResponseStatus().Message, "样品入箱");
            }
        }

        private void sampleUnpackaging(Sample sample)
        {
            if (sample == null) return;
            if(_currentPackage.Status==(int)PackageStatus.Inbound)
            {
                MessageBox.Show("当前箱子已入库,请联系仓库!", "撤销入箱");
                return;
            }
            var request = new SampleUnPackaging();
            request.Kvid=sample.Kvid;
            request.Location = _currentLocation;
            try
            {
                var resp = _client.Post(request);
                if (resp.Results.Count <= 0)
                {
                    return;
                }
                var record = resp.Results[0];
                if (_currentSamples == null) _currentSamples = new List<Sample>();
                if (_currentSamples.Exists(o => o.Kvid == record.Kvid))
                {
                    _currentSamples.RemoveAll(o => o.Kvid == record.Kvid);
                }
                this.Invoke(new Action(delegate
                {
                    dgvSamples.DataSource = null;
                }));
                this.Invoke(new Action(delegate
                {
                    dgvSamples.DataSource = _currentSamples;
                }));
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.GetResponseStatus().Message, "撤销入箱");
            }
        }
        private void setCurrentPackage(Sample package)
        {
            _currentPackage = new Sample();
            _currentPackage.PopulateWith(package);
            tbSetCurrentPackage.Enabled = _currentPackage == null;
            tbCurrentPackage.Text = _currentPackage.Name + (_currentPackage.PackageName.IsNullOrEmpty() ? "" : $"({_currentPackage.PackageName})");
            btnClearCurrentPackage.Enabled = _currentPackage != null;
            cbSetCurrentPackageNode.Enabled = _currentPackage.Status == (int)PackageStatus.Empty || _currentPackage.Status == (int)PackageStatus.Full;
            btnScanRfid.Enabled = _currentPackage.Status == (int)PackageStatus.Empty || _currentPackage.Status == (int)PackageStatus.Full;
            tbScanSample.Enabled = _currentPackage.Status == (int)PackageStatus.Empty || _currentPackage.Status == (int)PackageStatus.Full;
            tbScanSample.Text = "";
            if (_currentPackage.Status == (int)PackageStatus.Full || _currentPackage.Status == (int)PackageStatus.Inbound)
            {
                querySampleInPackaged();
            }
            if (_currentPackage.Status == (int)PackageStatus.Inbound)
            {
                MessageBox.Show("当前箱子已入库,无法继续操作!", "箱号设置");
                return;
            }
            cbSetCurrentPackageNode.SelectedIndex = 0;
            Thread.Sleep(200);
            btnScanRfid_Click(null, null);
        }

        private void searchPackage()
        {
            if (_client == null)
            {
                MessageBox.Show("请先登录!");
                return;
            }
            if (tbSetCurrentPackage.Text.IsNullOrEmpty())
            {
                MessageBox.Show("请输入箱号!");
                return;
            }
            var request = new SampleQuery();
            request.Name = tbSetCurrentPackage.Text;
            request.Type = SampleType.Package;
            var task = _client.PostAsync(request);
            task.Success(resp =>
            {
                if (resp.Results.Count <= 0)
                {
                    if (!ckbAutoCreatePackage.Checked)
                    {
                        _currentPackage = null;
                        MessageBox.Show("未找到箱号!", "箱号设置");
                        return;
                    }
                    else
                    {
                        var requestCreate=new PackageCreate();
                        requestCreate.Item = new Sample();
                        requestCreate.Item.Name = tbSetCurrentPackage.Text;
                        requestCreate.Item.Type = SampleType.Package;
                        requestCreate.Item.OperateTime = DateTime.Now;
                        var createTask = _client.PostAsync(requestCreate);
                        createTask.Success(res =>
                        {
                            if(res.Results.Count <= 0)
                            {
                                _currentPackage = null;
                                MessageBox.Show("创建箱号失败!", "箱号设置");
                                return;
                            }
                            var createPackage = res.Results.FirstOrDefault();
                            setCurrentPackage(createPackage);
                            return;
                        });
                        createTask.Error(ex =>
                        {
                            _currentPackage = null;
                            MessageBox.Show("创建箱号失败!", "箱号设置");
                            return;
                        });
                        return;
                    }
                }
                var package = resp.Results.FirstOrDefault();
                setCurrentPackage(package);
                //_currentPackage = new Sample();
                //_currentPackage.PopulateWith(package);
                //tbSetCurrentPackage.Enabled = _currentPackage == null;
                //tbCurrentPackage.Text = _currentPackage.Name + (_currentPackage.PackageName.IsNullOrEmpty() ? "" : $"({_currentPackage.PackageName})");
                //btnClearCurrentPackage.Enabled = _currentPackage != null;
                //cbSetCurrentPackageNode.Enabled = _currentPackage.Status == (int)PackageStatus.Empty || _currentPackage.Status == (int)PackageStatus.Full;
                //btnScanRfid.Enabled = _currentPackage.Status == (int)PackageStatus.Empty || _currentPackage.Status == (int)PackageStatus.Full;
                //tbScanSample.Enabled = _currentPackage.Status == (int)PackageStatus.Empty || _currentPackage.Status == (int)PackageStatus.Full;
                //tbScanSample.Text = "";
                //if (_currentPackage.Status == (int)PackageStatus.Full || _currentPackage.Status == (int)PackageStatus.Inbound)
                //{
                //    querySampleInPackaged();
                //}
                //if (_currentPackage.Status == (int)PackageStatus.Inbound)
                //{
                //    MessageBox.Show("当前箱子已入库,无法继续操作!", "箱号设置");
                //    return;
                //}
                //cbSetCurrentPackageNode.SelectedIndex = 0;
                //Thread.Sleep(200);
                //btnScanRfid_Click(null, null);
            });
            task.Error(err =>
            {
                _currentPackage = null;
                tbSetCurrentPackage.Enabled = true;
                tbCurrentPackage.Text = "";
                btnClearCurrentPackage.Enabled = false;
                cbSetCurrentPackageNode.SelectedItem = null;
                cbSetCurrentPackageNode.Enabled = false;
                btnScanRfid.Enabled = false;
                tbScanSample.Enabled = false;
                tbScanSample.Text = "";

                MessageBox.Show(err.Message, "箱号设置");
            });
        }

        private void reader_ConnectionLost(object sender, ConnectionChangedEventArgs e)
        {
            _tmr?.Stop();
            _tmr = null;
        }

        //private void reader_Disconnected(object sender, ConnectionChangedEventArgs e)
        //{
        //    _tmr?.Stop();
        //    _tmr = null;
        //}

        private void reader_Connected(object sender, ConnectionChangedEventArgs e)
        {
            //在这启动定时器
            _tmr = new System.Timers.Timer(1500);
            _tmr.Elapsed += new System.Timers.ElapsedEventHandler(tmr_Elapsed);
            _tmr.Start();
        }

        private void tmr_Elapsed(object sender, ElapsedEventArgs e)
        {
            try
            {
                _tmr?.Stop();//先停止定时器，防止重复触发
                var tid = ReaderInstance.ReadTid();//先读取Tid,即RFID标签的唯一标识
                if (string.IsNullOrEmpty(tid))//如果没有，那么就是没卡，直接返回
                {
                    return;
                }
                Thread.Sleep(150);//给下一个写卡让出时间
                var epc = ReaderInstance.ReadEpc();
                samplePrepackaging(tid, epc);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            finally
            {
                _tmr?.Start();
            }
        }

        #endregion

        private void btnLogin_Click(object sender, EventArgs e)
        {
            if (_client != null)
            {
                MessageBox.Show("登陆前先退出原连接");
                return;
            }
            btnLogin.Enabled = false;
            _client = new JsonServiceClient(tbxServiceUrl.Text);
            var auth = new Authenticate { UserName = tbxUserName.Text, Password = tbxPassword.Text, provider = "Kivii" };
            var task = _client.PostAsync(auth);
            task.Success(resp =>
            {
                initUserInfo(resp);
                btnLogin.Enabled = false;
                btnLogout.Enabled = !btnLogin.Enabled;
                tbxServiceUrl.Enabled = btnLogin.Enabled;
                tbxUserName.Enabled = btnLogin.Enabled;
                tbxPassword.Enabled = btnLogin.Enabled;
                lbLogStatus.Text = "登录成功";
                lbLogStatus.ForeColor = Color.Green;
                //tbSetCurrentPackage.Enabled = !btnLogin.Enabled;
                setDefault(tbxServiceUrl, tbxUserName, tbxPassword);
            }, true);
            task.Error(err =>
            {
                btnLogin.Enabled = true;
                initUserInfo();
                _client.Dispose();
                _client = null;
                MessageBox.Show(err.Message, "Login Error");
            }, true);
        }

        private void btnLogout_Click(object sender, EventArgs e)
        {
            if (_client == null)
            {
                MessageBox.Show("未连接");
                return;
            }
            btnLogout.Enabled = false;
            var auth = new Authenticate { provider = "Logout" };
            var task = _client.PostAsync(auth);
            task.Success(resp =>
            {
                initControls();
                lbLogStatus.Text = "未登录";
                lbLogStatus.ForeColor = Color.Red;
                _client.Dispose();
                _client = null;
                initUserInfo();
            });
            task.Error(err =>
            {
                btnLogout.Enabled = true;
                MessageBox.Show(err.Message, "Logout Error");
            });
        }

        private void tbxPassword_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                btnLogin_Click(null, null);
            }
        }

        private void tbSetCurrentPackage_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                searchPackage();
            }
        }

        private void btnClearCurrentPackage_Click(object sender, EventArgs e)
        {
            _currentPackage = null;
            _currentSamples = null;
            tbSetCurrentPackage.Enabled = true;
            tbCurrentPackage.Text = "";
            btnClearCurrentPackage.Enabled = false;
            cbSetCurrentPackageNode.SelectedItem = null;
            cbSetCurrentPackageNode.Enabled = false;
            btnScanRfid.Enabled = false;
            tbScanSample.Enabled = false;
            tbScanSample.Text = "";

            dgvSamples.DataSource = null;
        }

        private void cbSetCurrentPackageNode_TextChanged(object sender, EventArgs e)
        {
            tbCurrentPackageNode.Text = cbSetCurrentPackageNode.Text;
            if (_currentPackage != null) _currentPackage.PackageName = cbSetCurrentPackageNode.Text;
        }

        private void dgvSamples_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
        {
            dgvSamples.TopLeftHeaderCell.Value = "序号";
            //自动编号，与数据无关
            Rectangle rectangle = new Rectangle(e.RowBounds.Location.X,
               e.RowBounds.Location.Y,
               dgvSamples.RowHeadersWidth - 4,
               e.RowBounds.Height);
            TextRenderer.DrawText(e.Graphics,
                  (e.RowIndex + 1).ToString(),
                   dgvSamples.RowHeadersDefaultCellStyle.Font,
                   rectangle,
                   dgvSamples.RowHeadersDefaultCellStyle.ForeColor,
                   TextFormatFlags.VerticalCenter | TextFormatFlags.Right);
        }

        private void btnScanRfid_Click(object sender, EventArgs e)
        {
            #region 验证
            //if (ReaderInstance == null)
            //{
            //    MessageBox.Show("当前读卡器未连接.");
            //    return;
            //}
            if (_client == null)
            {
                MessageBox.Show("请先登录.");
                return;
            }
            if (_currentLocation == null)
            {
                MessageBox.Show("未获取当前位置.");
                return;
            }
            if (_currentPackage == null)
            {
                MessageBox.Show("未获取当前箱号.");
                return;
            }
            if (_currentPackage.Status == (int)PackageStatus.Inbound)
            {
                MessageBox.Show("当前箱子已入库,无法继续操作!");
                return;
            }
            #endregion
            if (ReaderInstance != null && ReaderInstance.State == ApplicationConnectionState.Connected)
            {
                ReaderInstance.CloseSpecComPort();
                ReaderInstance = null;
                btnScanRfid.Text = "开始扫描";
                btnScanRfid.BackColor = Color.PapayaWhip;
                btnScanRfid.ForeColor = Color.Chocolate;
            }
            else
            {

                initReader();
                #region 获取读卡器
                try
                {
                    ReaderInstance.AutoOpenComPort();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "连接读卡器失败");
                    ReaderInstance = null;
                    return;
                }
                #endregion
                btnScanRfid.Text = "停止扫描";
                btnScanRfid.BackColor = Color.DarkGray;
                btnScanRfid.ForeColor = Color.Black;
            }
        }

        private void dgvSamples_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            if (dgvSamples.Columns[e.ColumnIndex].CellType != typeof(DataGridViewButtonCell)) return;
            if (_client == null)
            {
                MessageBox.Show("未连接");
                return;
            }
            var currentRowSample = _currentSamples[e.RowIndex];
            if (currentRowSample == null) return;
            sampleUnpackaging(currentRowSample);
        }

        private void tbScanSample_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                if (_client == null)
                {
                    MessageBox.Show("请先登录.");
                    return;
                }
                if (_currentLocation == null)
                {
                    MessageBox.Show("未获取当前位置.");
                    return;
                }
                if (_currentPackage == null)
                {
                    MessageBox.Show("未获取当前箱号.");
                    return;
                }
                if (_currentPackage.Status == (int)PackageStatus.Inbound)
                {
                    MessageBox.Show("当前箱子已入库,无法继续操作!");
                    return;
                }
                samplePrepackaging(null, null, tbScanSample.Text);
            }
        }
    }
}
