using ButcherFactory.BO;
using ButcherFactory.BO.Rpcs;
using ButcherFactory.BO.Utils;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using ButcherFactory.Utils;
using ButcherFactory.BO.LocalBL;
using ButcherFactory.Controls;
using HidLibrary.Honeywell1902Series;

namespace ButcherFactory.SegmentInStore_
{
  public partial class SegmentInStoreForm : Form, IWithRoleForm
  {
    #region IWithRoleForm
    public List<short> RoleName
    {
      get { return new List<short> { (short)设备类别.扫码入库 }; }
    }

    public Form Generate()
    {
      return this;
    }
    #endregion

    Thread uploadData;
    Thread checkHasData;
    BindingList<SegmentInStore> inStoreList;
    BindingList<SegmentInStore> unInstoreList;
    BindingList<SegmentCodeError> exceptionList;
    BindingList<SegmentInStore> backStoreList;
     private static Scanner1902 _scanner;
    long? storeID;
    bool isBack = false;


    public SegmentInStoreForm()
    {
      InitializeComponent();
      netStateWatch1.GetConnectState = () => LoginUtil.TestConnection(500);
      this.FormClosing += delegate
      {
        if (uploadData != null && uploadData.IsAlive)
          uploadData.Abort();
        if (checkHasData != null && checkHasData.IsAlive)
          checkHasData.Abort();
        if (_scanner != null)
        {
          _scanner.StopListen();
          _scanner.Dispose();
        }
      };

      storeSelect.SelectedIndexChanged += delegate
      {
        if (storeSelect.SelectedValue == null)
          storeID = null;
        else
          storeID = (long)storeSelect.SelectedValue;
        XmlUtil.SerializerObjToFile(new SegmentInStoreFormConfig { StoreID = storeID });
      };
    }

    protected override void OnLoad(EventArgs e)
    {
      base.OnLoad(e);
      inStoreList = new BindingList<SegmentInStore>();
      var initTask = new Thread(LoadBind);
      initTask.Start();
      uploadData = new Thread(UpLoadLocalData);
      uploadData.Start();


      var vid = Int32.Parse("0C2E", System.Globalization.NumberStyles.HexNumber);
      var pid = Int32.Parse("0927", System.Globalization.NumberStyles.HexNumber);
      _scanner = Scanner1902.Enumerate(vid, pid).FirstOrDefault();
      if (_scanner != null)
      {
        _scanner.DataRecieved += ScannerDataRecieved;
        _scanner.StartListen();
      }
      else
      {
        MessageBox.Show("请连接扫码枪后重新启动程序！");
      }
    }

    private void LoadBind()
    {
      BLUtil.DeleteLocalDb<SegmentInStore>();
      if (netStateWatch1.NetState)
      {
        BaseInfoSyncRpc.SyncBaseInfo<WorkUnit>();
        BaseInfoSyncRpc.SyncProductBatch(1);
        BaseInfoSyncRpc.SyncBaseInfo<Store>();
      }
      this.Invoke(new Action(() =>
      {
        var config = XmlUtil.DeserializeFromFile<SegmentInStoreFormConfig>();
        var m = config.StoreID;
        storeSelect.EBindComboBox<Store>(x => x.ID == m);
        BindInStoreGrid();
        BindExceptionGrid();
        BindBackGrid();
        BindUnInstall();
      }));
    }

    private void BindUnInstall()
    {
      unInstoreList = new BindingList<SegmentInStore>(SegmentInStoreBL.GetUnInStoreList());
      unInstoreGrid.DataSource = unInstoreList;
      RefreshUnInStore();
    }

    object _lockUn = new object();
    void RefreshUnInStore()
    {
      lock (_lockUn)
        unInstoreGrid.Refresh();
    }

    private void BindInStoreGrid()
    {
      inStoreList = SegmentInStoreBL.GetInStoreByStateList(0);
      inStoreGrid.DataSource = inStoreList;
      RefreshInStore();
    }

    private void BindExceptionGrid()
    {
      exceptionList = SegmentInStoreBL.GetExceptionList();
      exceptionGrid.DataSource = exceptionList;
      exceptionGrid.Refresh();
    }

    private void BindBackGrid()
    {
      backStoreList = SegmentInStoreBL.GetInStoreByStateList(1);
      backStoreGrid.DataSource = backStoreList;
      backStoreGrid.Refresh();
    }

    private void UpLoadLocalData()
    {
      while (true)
      {
        try
        {
          if (netStateWatch1.NetState)
            SegmentInStoreBL.UploadSegmentInstoreInfo();
        }
        catch { }
        Thread.Sleep(1000);
      }
    }

    private void ScannerDataRecieved(byte[] data)
    {
      var code = ControlsUtil.ParseCode(Encoding.ASCII.GetString(data));
      if (string.IsNullOrEmpty(code))
        return;
      this.Invoke(new Action(() =>
      {
        barCodeBox.Text = code;
        if (isBack)
        {
          var idx = backStoreList.Any() ? backStoreList.First().RowIndex.Value : 0;
          var msg = SegmentInStoreBL.SetAsBacking(code, idx + 1);
          if (!string.IsNullOrEmpty(msg))
          {
            InsertExceptionInfo(code, msg);
            ControlsUtil.PlanVoice(msg);
            //InfoBox.Show("错误", msg, Color.Red, 1, this);
            return;
          }
          BindBackGrid();
          var fir = inStoreList.FirstOrDefault(x => x.BarCode == code);
          if (fir != null)
          {
            inStoreList.Remove(fir);
            RefreshInStore();
          }
        }
        else
        {
          var idx = inStoreList.Any() ? inStoreList.First().RowIndex.Value : 0;
          var first = new SegmentInStore() { Store_ID = storeID, BarCode = code, RowIndex = idx + 1 };
          var msg = SegmentInStoreBL.InsertInStore(first);
          if (!string.IsNullOrEmpty(msg))
          {
            InsertExceptionInfo(code, msg);
            ControlsUtil.PlanVoice(msg);
            //InfoBox.Show("错误", msg, Color.Red, 1, this);
            return;
          }
          inStoreList.Insert(0, first);
          if (inStoreList.Count > 30)
            inStoreList.RemoveAt(30);
          if (first.Weight == null)
          {
            checkHasData = new Thread(new ParameterizedThreadStart(GetInfoFromServer));
            checkHasData.Start(first);
          }
        }
      }));
    }

    private void GetInfoFromServer(object obj)
    {
      var entity = obj as SegmentInStore;
      SegmentInStoreBL.RefreshFromServer(entity);
      if (entity.Weight == null)
      {
        this.Invoke(new Action(() =>
        {
          var msg = "条码无效";
          InsertExceptionInfo(entity.BarCode, msg);

          SegmentInStoreBL.Delete(entity.ID);
          inStoreList.Remove(entity);
          ControlsUtil.PlanVoice(msg);
          //InfoBox.Show("错误", msg, Color.Red, 1, this);
        }));
      }
      this.Invoke(new Action(() =>
      {
        RefreshInStore();
        var first = unInstoreList.FirstOrDefault(x => x.BarCode == entity.BarCode);
        if (first != null)
        {
          try
          {
            unInstoreList.Remove(first);
            RefreshUnInStore();
          }
          catch { }
        }
      }));
    }

    object lc = new object();
    void RefreshInStore()
    {
      lock (lc)
        inStoreGrid.Refresh();
    }

    void InsertExceptionInfo(string barCode, string msg)
    {
      var error = new SegmentCodeError()
      {
        BarCode = barCode,
        ExceptionInfo = msg
      };
      SegmentInStoreBL.InsertSegmentCodeError(error);
      exceptionList.Insert(0, error);
      if (exceptionList.Count > 20)
        exceptionList.RemoveAt(20);
      exceptionGrid.Refresh();
    }

    private void backBtn_Click(object sender, EventArgs e)
    {
      isBack = !isBack;
      backBtn.Text = isBack ? "等待退库" : "退库";
    }

    private void deleteBtn_Click(object sender, EventArgs e)
    {
      if (MessageBox.Show("确定删除该入库信息？", "删除确认", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) != DialogResult.OK)
        return;
      if (backStoreGrid.CurrentRow == null)
        return;
      var id = (long)backStoreGrid.CurrentRow.Cells["B_ID"].Value;
      SegmentInStoreBL.Delete(id);
      var tag = backStoreList.First(x => x.ID == id);
      backStoreList.Remove(tag);
      backStoreGrid.Refresh();
    }

    private void submitBtn_Click(object sender, EventArgs e)
    {
      if (backStoreList.Count == 0)
        return;
      var ids = backStoreList.Select(x => x.ID);
      SegmentInStoreBL.SubmitBackStore(ids);
      backStoreList.Clear();
      backStoreGrid.Refresh();
    }

    private void inStoreViewBtn_Click(object sender, EventArgs e)
    {
      new InStoreSummaryView().ShowDialog();
    }

    private void clearErrorBtn_Click(object sender, EventArgs e)
    {
      SegmentInStoreBL.ClearErrorMsg();
      exceptionList.Clear();
      exceptionGrid.Refresh();
    }

    private void refreshBtn_Click(object sender, EventArgs e)
    {
      BindUnInstall();
    }
  }
}
