using ButcherFactory.BO;
using ButcherFactory.BO.LocalBL;
using ButcherFactory.BO.Rpcs;
using ButcherFactory.BO.Utils;
using ButcherFactory.Dialogs;
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 WinFormControl;
using ButcherFactory.Utils;
using NotAuto = ButcherFactory.SegmentProduction_;
using ButcherFactory.Controls;

namespace ButcherFactory.SegmentProductionAuto_
{
  public partial class SegmentProductionAutoForm : Form, IWithRoleForm
  {
    public List<short> RoleName
    {
      //get { return new List<short> { (short)设备类别.分割生产自动化 }; }
      get { return new List<short> { (short)设备类别.分割生产 }; }
    }

    public Form Generate()
    {
      return this;
    }

    Thread uploadData;
    Thread checkInStoreState;
    Thread initTask;
    BindingList<SegmentProduction> historyList;
    BindingList<TotalCode> allCode;
    Dictionary<string, List<ClientGoodsSet_Detail>> goodsSetDic;
    long? batchID;
    DateTime? batchDate;
    NotAuto.SegmentProductionFormConfig config;
    public SegmentProductionAutoForm()
    {
      InitializeComponent();
      netStateWatch1.GetConnectState = () => LoginUtil.TestConnection(500);
      this.FormClosing += SegmentProductionAutoForm_FormClosing;
      workUnitSelect.SelectedIndexChanged += delegate
      {
        if (workUnitSelect.SelectedValue == null)
          config.WorkUnitID = null;
        else
          config.WorkUnitID = (long)workUnitSelect.SelectedValue;
        XmlUtil.SerializerObjToFile(config);
      };
      productBatchSelect.SelectedIndexChanged += delegate
      {
        if (productBatchSelect.SelectedValue == null)
        {
          batchID = null;
          batchDate = null;
        }
        else
        {
          var entity = productBatchSelect.SelectedItem as ProductBatch;
          batchID = entity.ID;
          batchDate = entity.Date;
        }
      };
    }

    void SegmentProductionAutoForm_FormClosing(object sender, FormClosingEventArgs e)
    {
      var unSyncCount = SegmentProductionBL.GetUnSyncCount();
      if (unSyncCount > 0)
      {
        if (MessageBox.Show(string.Format("{0}条数据等待上传，确认关闭？", unSyncCount), "关闭确认", MessageBoxButtons.OKCancel) != DialogResult.OK)
        {
          e.Cancel = true;
        }
      }

      if (initTask != null && initTask.IsAlive)
        initTask.Abort();
      if (uploadData != null && uploadData.IsAlive)
        uploadData.Abort();
      if (checkInStoreState != null && checkInStoreState.IsAlive)
        checkInStoreState.Abort();
    }
    WeightDetails mCache;
    protected override void OnLoad(EventArgs e)
    {
      base.OnLoad(e);
      initTask = new Thread(LoadBind);
      initTask.Start();

      checkInStoreState = new Thread(CheckInStored);
      checkInStoreState.Start();

      uploadData = new Thread(UpLoadLocalData);
      uploadData.Start();
      mCache = XmlUtil.DeserializeFromFile<WeightDetails>();
      var del = new List<long>();
      if (mCache.Cache == null)
      {
          mCache.Cache = new Dictionary<long, List<decimal>>();
      }
      foreach (var item in mCache.Cache)
      {
          if (item.Value == null || item.Value.Count == 0)
          {
              del.Add(item.Key);
          }
      }
      foreach (var v in del)
      {
          mCache.Cache.Remove(v);
      }
      wDic = mCache.Cache;

    }

    void LoadBind()
    {
      BLUtil.DeleteLocalDb<SegmentProduction>();
      SegmentProductionBL.DeleteBefore();
      GetBasicInfo();
    }

    bool ok = false;
    bool bind = false;
    void GetBasicInfo()
    {
      while (!ok)
      {
        try
        {
          var changed = BaseInfoSyncRpc.SyncGoodsByTag(ApplyClient.分割品);
          changed = BaseInfoSyncRpc.SyncBaseInfo<WorkUnit>() || changed;
          changed = BaseInfoSyncRpc.SyncProductBatch(1) || changed;
          ok = true;
          if (changed || !bind)
            BindBasicInfo();
          this.Invoke(new Action(() =>
          {
            msglbl.Text = string.Empty;
          }));
        }
        catch
        {
          if (!bind)
          {
            BindBasicInfo();
            bind = true;
          }
        }
        Thread.Sleep(500);
      }
    }

    void BindBasicInfo()
    {
      this.Invoke(new Action(() =>
      {
        productBatchSelect.EBindComboBox<ProductBatch>(null, 6, "Date");
        config = XmlUtil.DeserializeFromFile<NotAuto.SegmentProductionFormConfig>();
        var m = config.WorkUnitID;
        workUnitSelect.EBindComboBox<WorkUnit>(x => x.ID == m, top: 100);

        BindGoods();
        BindGrid();
      }));
    }

    void BindGoods()
    {
      goodsSetDic = FormClientGoodsSetBL.GetSelectedDetail();
      flowLayoutPanel1.Controls.Clear();
      flowLayoutPanel2.Controls.Clear();
      foreach (var item in goodsSetDic)
      {
        var btn = new ColorButton() { Width = 100, Height = 62, Text = item.Key, Font = new Font("宋体", 15), Margin = new Padding(15, 3, 15, 0), EnableGroup = true };
        btn.Click += GroupGoodsSetClick;
        flowLayoutPanel1.Controls.Add(btn);
      }
    }

    Color goodsColor = Color.FromArgb(250, 120, 24);
    string groupKey = string.Empty;
    public Dictionary<long, List<decimal>> wDic = new Dictionary<long, List<decimal>>();
    void GroupGoodsSetClick(object sender, EventArgs e)
    {
        flowLayoutPanel2.Controls.Clear();
        var groupBtn = sender as ColorButton;
        groupKey = groupBtn.Text;
        var arr = goodsSetDic[groupKey];
        int i = 0;
        foreach (var item in arr)
        {
            var bTag = new ButtonTag();
            if ((item.EachNumber ?? 0) > 0)
            {
                bTag.Label.MaxCount = item.EachNumber.Value;
                if (wDic.ContainsKey(item.Goods_ID))
                {
                   var l = wDic[item.Goods_ID];
                   bTag.Label.Text = string.Format("{0}-{1}", item.EachNumber.Value, l.Count);
                }
                else
                {
                    bTag.Label.Text = string.Format("{0}-0", item.EachNumber.Value);
                }
                bTag.Button.Click += delegate
                {
                    if (batchID == null)
                        throw new Exception("请先选择批次");
                    var weight = uWeightControl1.Weight;
#if DEBUG
                    if (weight == 0)
                        weight = (item.StandardWeightLow ?? 4.0m) + 0.1m;
#endif
                    if (weight == 0)
                        throw new Exception("重量不能为0");
                    if (item.StandardWeight.HasValue)
                    {
                        if (weight < (item.StandardWeightLow ?? 0) || weight > (item.StandardWeightUp ?? 0))
                            throw new Exception(string.Format("重量必须在{0:#0.######}-{1:#0.######}之间", item.StandardWeightLow, item.StandardWeightUp));
                        weight = item.StandardWeight.Value;
                    }
                    List<decimal> l = null;
                    if (wDic.ContainsKey(item.Goods_ID))
                    {
                        l = wDic[item.Goods_ID];
                        if (l.Count >= item.EachNumber.Value)
                        { 
                            l.Clear();
                        }
                        l.Add(weight);
                    }
                    else
                    {
                        wDic.Add(item.Goods_ID, l = new List<decimal>() { weight });
                    }
                    bTag.Label.MinCount = l.Count();
                    if (l.Count >= item.EachNumber.Value)
                    {
                        weight = l.Sum(x => x);
                        InsertSegmentProduction(item, weight); 
                    }
                    mCache.Cache = wDic;
                    XmlUtil.SerializerObjToFile(mCache);
                };

                bTag.Label.Click += delegate
                {
                    List<decimal> l = new List<decimal>(0);
                    if (wDic.ContainsKey(item.Goods_ID))
                    {
                        l = wDic[item.Goods_ID];
                    }
                    new WeightView(this, bTag).ShowDialog();
                };
            }
            else
            {
                bTag.Label.Visible = false;
                bTag.Button.Click += GoodsBtnClick;
            }
           
            bTag.Button.Tag = item;
            bTag.Button.Text = item.Goods_Name;
            bTag.Button.Font = new Font("黑体", 15, FontStyle.Bold);
            bTag.Button.BackColor = Color.Black;
            bTag.Button.Margin = new Padding(20, 10, 20, 35);
            bTag.Button.PlaySound = true;
            bTag.Button.ForeColor = Color.White;
            bTag.Button.Width = 140;
            bTag.Button.Height = 90;
            flowLayoutPanel2.Controls.Add(bTag);
            i++;
        }
    }

    void GoodsBtnClick(object sender, EventArgs e)
    {
      if (batchID == null)
        throw new Exception("请先选择批次");
      var btn = sender as ColorButton;
      var detail = btn.Tag as ClientGoodsSet_Detail;
      var weight = uWeightControl1.Weight;
#if DEBUG
      if (weight == 0)
          weight = (detail.StandardWeightLow ?? 4.0m) + 0.1m;
#endif
        if (weight == 0)
          throw new Exception("重量不能为0");

      if (detail.StandardWeight.HasValue)
      {
          if (weight < (detail.StandardWeightLow ?? 0) || weight > (detail.StandardWeightUp ?? 0))
              throw new Exception(string.Format("重量必须在{0:#0.######}-{1:#0.######}之间", detail.StandardWeightLow, detail.StandardWeightUp));
          weight = detail.StandardWeight.Value;
      }
      InsertSegmentProduction(detail, weight);
    }

    private void InsertSegmentProduction(ClientGoodsSet_Detail detail, decimal weight)
    { 
        var pics = int.Parse(numberInput.Text);
        if (pics <= 0)
            pics = 1;
        else if (pics > 50)
            pics = 50;
        SegmentProduction entity = null;
        for (var i = 0; i < pics; i++)
        {
            entity = new SegmentProduction();
            entity.Goods_ID = detail.Goods_ID;
            entity.Weight = weight;
            entity.WorkUnit_ID = config.WorkUnitID;
            entity.ProductBatch_ID = batchID.Value;
            entity.StandardPic = detail.StandardPic;
            if (!string.IsNullOrEmpty(statisticNumberBox.Text))
                entity.StatisticNumber = decimal.Parse(statisticNumberBox.Text);
            if (_totalCode == null || _codePanel==null)
            {
                throw new Exception(string.Format("请先选择总码！" ));
            }
            entity.TotalCode_ID = _totalCode.ID;
            SegmentProductionBL.InsertAndSetGroupID(entity, batchDate.Value);
            entity.Goods_Code = detail.Goods_Code;
            entity.Goods_Name = detail.Goods_Name;
            entity.Goods_Spec = detail.Goods_Spec;
            entity.MainUnit = detail.MainUnit;
            entity.ShotPrintName = detail.ShotPrintName;
          
           _codePanel.Add(initSegmentBt(entity));
           
            historyList.Insert(0, entity);

            if (historyList.Count > 30)
                historyList.RemoveAt(30);
            if (barPrintCheck.Checked)
            {
                var template = config.Template;
                if (detail.GoodsType.HasValue)
                    template = detail.GoodsType == 0 ? "SegmentProductionPrint.html" : "SegmentProductionPrint1.html";
                NotAuto.SegmentProductionPrint.Print(entity, batchDate, template);
                var log = new SegmentLog(entity.BarCode, "打印");
                log.Message = string.Format("存货名称：{0} 重量：{1:#0.###}", entity.Goods_Name, entity.Weight);
                SegmentProductionBL.InsertLog(log);
            }
        }
        GoodsLabel.Text = detail.Goods_Name;
     
        var thd = new Thread(new ParameterizedThreadStart(RefreshTask));
        thd.Start(entity); 
    }

    SegmentProduction current;
    private  ColorButton initSegmentBt(SegmentProduction entity)
    {
        var bt = new ColorButton() { Text = entity.ShortCode };
        bt.Tag = entity;
        bt.Width = 110;
        bt.Height = 50;
        bt.Font = new Font("黑体", 13, FontStyle.Bold);
        bt.BackColor = Color.DarkCyan;
        bt.SelectedColor = Color.DarkOrange;
        bt.Click += delegate
        { 
            bt.Selected = !bt.Selected;
            if (bt.Selected)
            {
                current = entity;
                GoodsLabel.Text = entity.Goods_Name;
            }
            else
            {
                current = null; 
                GoodsLabel.Text = "";
            }
            foreach (var bt2 in segmentButtons)
            {
                if (bt2.Text != entity.ShortCode && bt2.Selected)
                {
                    bt2.Selected = false;
                    bt2.Invalidate();
                }
            }

        };
        segmentButtons.Add(bt);
        return bt;
    }

    void RefreshTask(object obj)
    {
        var entity = obj as SegmentProduction;
        var list = SegmentProductionBL.GetProductTask(batchDate ?? DateTime.Today, entity);
        this.Invoke(new Action(() =>
        {
            taskDataGrid.DataSource = list;
            taskDataGrid.Refresh();
        }));
    }

    List<ColorButton> codeButtons = new List<ColorButton>(0);
    List<ColorButton> segmentButtons = new List<ColorButton>(0);

    void BindGrid()
    {
      historyList = SegmentProductionBL.GetListByState(true);
      allCode = SegmentProductionBL.GetTotalCode(DateTime.Now);

      RefreshCodePanel();
 
      var first = historyList.FirstOrDefault();
      if (first != null)
        GoodsLabel.Text = first.Goods_Name;
    }

    private void RefreshCodePanel()
    {
        flowLayoutPanel3.Controls.Clear();
        codeButtons.Clear();
        foreach (var item in allCode)
        {
            var details = historyList.Where(x => x.TotalCode_ID == item.ID);
            var n = new CodePanel();
            AddCodeButton(n, item);
            foreach (var seg in details)
            {
                n.Add(initSegmentBt(seg));
            }
            flowLayoutPanel3.Controls.Add(n);
        }
    }

    void UpLoadLocalData()
    {
      while (true)
      {
        try
        {
          //this.Invoke(new Action(() =>
          //{
          if (netStateWatch1.NetState)
            SegmentProductionBL.UploadSegmentInfo();
          //}));
        }
        catch { }
        Thread.Sleep(2000);
      }
    }

    private void CheckInStored()
    {
      while (true)
      {
        try
        {
          if (netStateWatch1.NetState)
          {
            if (historyList.Any())
            {
              var arr = historyList.Reverse().Take(20);
              var inStored = SegmentProductionBL.GetInStoreState(arr.Select(x => x.BarCode).ToList());
              var tag = arr.Where(x => inStored.Contains(x.BarCode));
              if (tag.Any())
              {
                SegmentProductionBL.SetInStored(tag.Select(x => x.ID).ToList());
                this.Invoke(new Action(() =>
                {
                  foreach (var item in tag)
                    historyList.Remove(item);
                  //historyDataGrid.ClearSelection();
                  //historyDataGrid.Refresh();
                }));
              }
            }
          }
        }
        catch { }
        Thread.Sleep(5000);
      }
    }

    private void closeBtn_Click(object sender, EventArgs e)
    {
      Close();
    }

    private void goodsSetBtn_Click(object sender, EventArgs e)
    {
      new ClientGoodsSetDialog().ShowDialog();
      BindGoods();
    }

    private void rePrintBtn_Click(object sender, EventArgs e)
    {
      if (barPrintCheck.Checked)
      {
        if (historyList.Count == 0)
          throw new Exception("请先选择要补打的记录");
        SegmentProduction item;
        
        if (current != null)
            item = current;
        else
            item = historyList.First();
        var template = config.Template;
        var goodsType = SegmentProductionBL.GetGoodsType(item.Goods_ID);
        if (goodsType.HasValue)
          template = goodsType == 0 ? "SegmentProductionPrint.html" : "SegmentProductionPrint1.html";
        NotAuto.SegmentProductionPrint.Print(item, batchDate, template);
        var log = new SegmentLog(item.BarCode, "补打");
        log.Message = string.Format("存货名称：{0} 重量：{1:#0.###}", item.Goods_Name, item.Weight);
        SegmentProductionBL.InsertLog(log);
      }
    }

    private void templateBtn_Click(object sender, EventArgs e)
    {
      new TemplateSelector(config).ShowDialog();
    }

    private void deleteBtn_Click(object sender, EventArgs e)
    {
   
        if (current == null)
            return;
      if (MessageBox.Show("确定删除选中记录？", "删除确认", MessageBoxButtons.OKCancel) != DialogResult.OK)
        return;

      //var tag = historyDataGrid.SelectedRows[0].DataBoundItem as SegmentProduction;
  
      if (current.CreateTime.AddMinutes(1) < DateTime.Now)
      {
        MessageBox.Show("已超出可删除时间范围");
        return;
      }
      SegmentProductionBL.Delete(current); 
      historyList.Remove(current);
      RefreshCodePanel();
      var thd = new Thread(new ParameterizedThreadStart(RefreshTask));
      thd.Start(current);
    }

    private void logBtn_Click(object sender, EventArgs e)
    {
      new LogForm().ShowDialog();
    }

    private void StatisticNumberBox_MouseClick(object sender, MouseEventArgs e)
    {
      var keyBoard = new NumberPad();
      if (keyBoard.ShowDialog() == true)
      {
        var box = (sender as TextBox);
        if (string.IsNullOrEmpty(keyBoard.Result))
          box.Text = string.Empty;
        else
        {
          decimal num = 0;

          if (!decimal.TryParse(keyBoard.Result, out num))
            throw new Exception("数量输入有误");
          box.Text = keyBoard.Result;
        }
      }
    }

    private void ViewTaskBtn_Click(object sender, EventArgs e)
    {
      if (string.IsNullOrEmpty(groupKey))
        throw new Exception("请选择存货分组");
      if (batchID == null)
        throw new Exception("请先选择批次");
      if (goodsSetDic == null)
        throw new Exception("请选择存货分组");
      var arr = goodsSetDic[groupKey];
      if(arr.Count==0)
        throw new Exception("分组中没有任何存货");
      var goods = arr.Select(x => new Goods { Code = x.Goods_Code, Name = x.Goods_Name, ID = x.Goods_ID });
      new ViewTaskForm(batchDate ?? DateTime.Today, batchID.Value, goods).ShowDialog();
    }

    private void numberInput_MouseClick(object sender, MouseEventArgs e)
    {
      var keyBoard = new NumberPad();
      if (keyBoard.ShowDialog() == true)
      {
        var box = (sender as TextBox);
        if (string.IsNullOrEmpty(keyBoard.Result))
          box.Text = "1";
        else
        {
          int num = 0;
          if (!int.TryParse(keyBoard.Result, out num))
            throw new Exception("数量输入有误");
          if (num <= 0)
            num = 1;
          if (num > 50)
            num = 50;
          box.Text = num.ToString();
        }
      }
    }
   
    CodePanel _codePanel;
    TotalCode _totalCode;
    private void colorButton1_Click(object sender, EventArgs e)
    {
        var n = new CodePanel();
        
        var tCode = SegmentProductionBL.InsertTotalCode(new TotalCode());
        AddCodeButton(n, tCode,true);
        flowLayoutPanel3.Controls.Add(n);
    }

    private void AddCodeButton(CodePanel n, TotalCode tCode,bool add=false)
    {
        n.Button.Tag = tCode;
        n.Button.Text = tCode.ShortCode;
        n.Button.Click += delegate
        {

            n.Button.Selected = !n.Button.Selected;
            if (n.Button.Selected)
            {
                _codePanel = n;
                _totalCode = tCode;
            }
            else
            {
                _codePanel = null;
                _totalCode = null;
            }
            foreach (var bt in codeButtons)
            {
                if (bt.Text != n.Button.Text && bt.Selected)
                {
                    bt.Selected = false;
                    bt.Invalidate();
                }
            }

        };
        if (add)
        {
            _codePanel = n;
            n.Button.Selected = true;
            _totalCode = tCode;
            foreach (var bt in codeButtons)
            {
                if (bt.Selected)
                {
                    bt.Selected = false;
                    bt.Invalidate();
                }
            }
        }
        codeButtons.Add(n.Button);
    }

    private void colorButton2_Click(object sender, EventArgs e)
    {
        if (_totalCode == null || _codePanel == null)
        {
            throw new Exception(string.Format("请先选择总码！"));
        }
       var dmos= historyList.Where(x => x.TotalCode_ID == _totalCode.ID).ToArray();
       if (dmos.Length == 0)
       {
           throw new Exception(string.Format("此码不包含任何产品！"));
       }
        NotAuto.SegmentSumCodePrint.Print(dmos, "SegmentSumCode.html");
        var log = new SegmentLog(dmos[0].TotalCode_Code, "总码");
        log.Message = string.Format("总码：{0}  ", dmos[0].TotalCode_Code);
        SegmentProductionBL.InsertLog(log);
    }
  }
}
