using BO;
using BO.BO.BaseInfo;
using BO.BO.Bill;
using BO.Utils;
using BO.Utils.BillRpc;
using BWP.WinFormControl;
using BWP.WinFormControl.WeightDataFormat;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WeighAndGrading
{
  public partial class GradeFrom : Form, IAfterLogin
  {
    #region IAfterLogin
    public string RoleName
    {
      get { return "定级员"; }
    }

    public Form Generate()
    {
      if (string.IsNullOrEmpty(ButcherAppContext.Context.UrlConfig.OfflineSqlConnection))
        throw new Exception("请先设置离线数据库并保存");
      if (!LocalDmoSession.ConnectionTest())
        throw new Exception("离线数据库连接失败");
      return this;
    }
    #endregion
    private delegate void InvokeHandler();
    public const string DATA_PATH = "G_A_W_Data";
    const short TANG_TECH = 0;
    const short MAO_TECH = 1;
    List<GradeAndWeight> tangList;
    List<GradeAndWeight> maoList;
    BindingList<GradeAndWeight_Detail> details;

    List<long> localTang, localMao;
    string maoFilePath, tangFilePath;
    string discontPath = Path.Combine(DATA_PATH, "Disconts.xml");

    bool connection = false;

    SerialPort weightPort;
    int maxIndex = 0;
    ConcurrentQueue<GradeAndWeight_Detail> noLivestockList;

    ConcurrentQueue<GradeAndWeight_Detail> noWeightList;
    Thread syncWork;
    Thread syncToServer;
    #region weightNeed
    private IDataFormat _dataFormat;
    private Thread _inQueryThread;
    private bool _mainProcessIsRun;
    readonly StringBuilder _dataStrBuilder = new StringBuilder();
    #endregion

    public GradeFrom()
    {
      InitializeComponent();
      butcherTimeInput.Date = DateTime.Today;
      tangGridView.AutoGenerateColumns = false;
      tangGridView.DataSource = null;
      maoGridView.AutoGenerateColumns = false;
      maoGridView.DataSource = null;
      historyGrid.AutoGenerateColumns = false;
      if (!Directory.Exists(DATA_PATH))
        Directory.CreateDirectory(DATA_PATH);
      maoFilePath = Path.Combine(DATA_PATH, "MaoList.xml");
      tangFilePath = Path.Combine(DATA_PATH, "TangList.xml");
      connection = ButcherAppContext.Context.UserConfig.Connection;
      AddLivestockBtn();
      BuildDiscontPanel(true);
      weightPort = new SerialPort();
      this.FormClosing += delegate
      {
        if (_inQueryThread != null && _inQueryThread.IsAlive)
          DisableWeight();
        if (syncWork != null && syncWork.IsAlive)
          syncWork.Abort();
        if (syncToServer != null && syncToServer.IsAlive)
          syncToServer.Abort();
      };
    }

    GradeAndWeight_Detail modifyDetail;

    //    private void GradeFrom_KeyPress(object sender, KeyPressEventArgs e)
    //    {
    //      Char keyChar = e.KeyChar;
    //      var key = keyChar.ToString().ToLower();
    //      foreach (Button btn in ttPanel.Controls)
    //      {
    //        var livestockTag = btn.Tag as CTuple<long, string, short, string>;
    //        if (livestockTag.Item4.ToLower() == key)
    //        {
    //          JiBieButtonClick(btn);
    //          SetJiBieSelectBackColor(btn.Text);
    //        }
    //      }
    //      foreach (Button btn in mbPanel.Controls)
    //      {
    //        var livestockTag = btn.Tag as CTuple<long, string, short, string>;
    //        if (livestockTag.Item4.ToLower() == key)
    //        {
    //          JiBieButtonClick(btn);
    //          SetJiBieSelectBackColor(btn.Text);
    //        }
    //      }
    //    }

    //点击 级别
    void JiBieButtonClick(Button btn)
    {
      if (details == null)
      {
        MessageBox.Show("请先同步数据");
        return;
      }
      btn.Enabled = false;
      SetlblSucessVisibleTrue();

      var livestockTag = btn.Tag as CTuple<long, string, short, string>;
      var tech = livestockTag.Item3 == TANG_TECH ? "烫褪" : "毛剥";


      if (modifyDetail == null)
      {
        StartPrintEntity(tech, null);
        AddDetail(livestockTag);
      }
      else
      {
        var needUpdate = modifyDetail.Technics != livestockTag.Item3;
        StartPrintEntity(tech, modifyDetail.Index);
        modifyDetail.Livestock_ID = livestockTag.Item1;
        modifyDetail.Livestock_Name = livestockTag.Item2;
        modifyDetail.Technics = livestockTag.Item3;
        modifyDetail.Technics_Name = livestockTag.Item3 == TANG_TECH ? "烫褪" : "毛剥";
        if (needUpdate)
        {
          if (modifyDetail.Technics == 0)//毛剥 到 烫褪
          {
            LocalGradeAndWeightBL.Update(modifyDetail, tangEntity);
            if (modifyDetail.Order.HasValue)
            {
              var first = maoList.First(x => x.Order == modifyDetail.Order);
              first.Already -= 1;
              maoGridView.Refresh();
            }
            tangEntity.Already += 1;
            tangGridView.Refresh();
          }
          else//烫褪 到 毛剥
          {
            LocalGradeAndWeightBL.Update(modifyDetail, maoEntity);
            if (modifyDetail.Order.HasValue)
            {
              var first = tangList.First(x => x.Order == modifyDetail.Order);
              first.Already -= 1;
              tangGridView.Refresh();
            }
            maoEntity.Already += 1;
            maoGridView.Refresh();
          }
        }
        else
          LocalGradeAndWeightBL.Update(modifyDetail, "Livestock_ID", "Livestock_Name", "Technics", "Technics_Name");
        noLivestockList = new ConcurrentQueue<GradeAndWeight_Detail>();
        var stack = new Stack<GradeAndWeight_Detail>();

        //找到锁定的最大id
        long suodingmaxsid = 0;
        var lostweightlist = details.Where(x => x.IsLostWeight).ToList();
        if (lostweightlist.Count > 0)
        {
          suodingmaxsid = lostweightlist.Max(x => x.SID);
        }
        //把没有级别的记录加进去
        var livestockNoNameList = details.Where(x => string.IsNullOrWhiteSpace(x.Livestock_Name));
        foreach (var item in livestockNoNameList)
        {
          if (item.SID > suodingmaxsid)
          {
            stack.Push(item);
          }
        }
        while (stack.Count > 0)
        {
          noLivestockList.Enqueue(stack.Pop());
        }


        historyGrid.Refresh();
        modifyDetail = null;
        modifyPanel.Hide();
      }

      SetlblSucessVisibleFalse();
      btn.Enabled = true;
    }

    void AddLivestockBtn()
    {
      var livestocks = new List<CTuple<long, string, short, string>>();
      var fileName = Path.Combine(DATA_PATH, "Livestocks.xml");
      if (connection)
      {
        livestocks = BaseInfoRpcUtil.GetLivestockList();
        XmlUtil.SerializerObjToFile(livestocks, fileName);
      }
      else
        livestocks = XmlUtil.DeserializeFromFile<List<CTuple<long, string, short, string>>>(fileName);
      foreach (var item in livestocks)
      {
        var btn = new Button() { Name = "_" + item.Item1, Text = item.Item2, Tag = item, Size = new Size(90, 75), TextAlign = ContentAlignment.MiddleCenter, Margin = new Padding { All = 15 }, Font = new Font("宋体", 18) };

        btn.Click += (sender, e) =>
        {
          //          btn.Enabled = false;
          //          Application.DoEvents();
          JiBieButtonClick(btn);
          #region  改到方法JiBieButtonClick（）里了



          //          if (details == null)
          //          {
          //            MessageBox.Show("请先同步数据");
          //            return;
          //          }
          //          var livestockTag = btn.Tag as CTuple<long, string, short>;
          //          if (modifyDetail == null)
          //            AddDetail(livestockTag);
          //          else
          //          {
          //            modifyDetail.Livestock_ID = livestockTag.Item1;
          //            modifyDetail.Livestock_Name = livestockTag.Item2;
          //            modifyDetail.Technics = livestockTag.Item3;
          //            modifyDetail.Technics_Name = livestockTag.Item3 == TANG_TECH ? "烫褪" : "毛剥";
          //            LocalGradeAndWeightBL.Update(modifyDetail, "Livestock_ID", "Livestock_Name", "Technics", "Technics_Name");
          //            historyGrid.Refresh();
          //            modifyDetail = null;
          //            modifyPanel.Hide();
          //          }

          #endregion

          //          btn.Enabled = true;
          //          Application.DoEvents();

          //var name = livestock.Technics == 0 ? "带皮白条" : "去皮白条";
          //Print(name, entity.Index);

        };
        if (item.Item3 == TANG_TECH)
        {
          ttPanel.Controls.Add(btn);
        }
        else
        {
          mbPanel.Controls.Add(btn);
        }
      }
      SetMargin(ttPanel);
      SetMargin(mbPanel);
    }



    //    private void SetJiBieSelectBackColor(string btnText)
    //    {
    //      foreach (Control control in ttPanel.Controls)
    //      {
    //        if (control.Text == btnText)
    //        {
    //          control.BackColor = Color.Aqua;
    //        }
    //        else
    //        {
    //          control.BackColor = SystemColors.Control;
    //        }
    //      }
    //
    //      foreach (Control control in mbPanel.Controls)
    //      {
    //        if (control.Text == btnText)
    //        {
    //          control.BackColor = Color.Aqua;
    //        }
    //        else
    //        {
    //          control.BackColor = SystemColors.Control;
    //        }
    //      }
    //
    //    }


    void SetMargin(FlowLayoutPanel panel)
    {
      for (var i = 0; i < panel.Controls.Count; i++)
      {
        var c = panel.Controls[i];
        if (i % 3 == 0)//left
          c.Margin = new Padding(0, c.Margin.Top, c.Margin.Right, c.Margin.Bottom);
        if ((i + 1) % 3 == 0)//right
          c.Margin = new Padding(c.Margin.Left, c.Margin.Top, 0, c.Margin.Bottom);
        if (i <= 2)//firstRow
          c.Margin = new Padding(c.Margin.Left, 0, c.Margin.Right, c.Margin.Bottom);
      }
    }

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

    private void syncBtn_Click(object sender, EventArgs e)
    {
      details = LocalGradeAndWeightBL.GetDetails(butcherTimeInput.Date.Value, 50);
      FillQueue();
      BindDetailGrid();
      if (details.Any())
        maxIndex = details.First().Index;
      if (syncWork == null || !syncWork.IsAlive)
      {
        syncWork = new Thread(Sync);
        syncWork.Start();
        syncBtn.BackColor = Color.FromArgb(15, 215, 107);
        syncBtn.ForeColor = Color.White;
      }
      else
      {
        syncWork.Abort();
        syncBtn.BackColor = Color.FromKnownColor(KnownColor.Control);
        syncBtn.ForeColor = Color.FromKnownColor(KnownColor.ControlText);
      }
    }

    void Sync()
    {
      while (true)
      {
        var bc = new BackgroundWorker();
        bc.DoWork += Bc_DoWork;
        bc.RunWorkerCompleted += Bc_RunWorkerCompleted;
        if (!bc.IsBusy)
        {
          bc.RunWorkerAsync();
        }
        //        this.Invoke(new InvokeHandler(delegate ()
        //        {
        //          BindTangGrid();
        //          BindMaoGrid();
        //        }));
        Thread.Sleep(5000);
      }
    }

    private void Bc_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
      this.BeginInvoke(new Action(() =>
      {
        BindTangGrid();
        BindMaoGrid();
      }));

    }

    private void Bc_DoWork(object sender, DoWorkEventArgs e)
    {
      BindTangGridFortangList();
      BindMaoGridFromaoList();
    }

    void FillQueue()
    {
      noWeightList = new ConcurrentQueue<GradeAndWeight_Detail>();
      noLivestockList = new ConcurrentQueue<GradeAndWeight_Detail>();
      var stack = new Stack<GradeAndWeight_Detail>();
      foreach (var item in details)
      {
        if (item.Livestock_ID == 0 || item.Weight == null || string.IsNullOrWhiteSpace(item.Livestock_Name))
          stack.Push(item);
        else
          break;
      }
      while (stack.Count > 0)
      {
        var bottom = stack.Pop();
        if (bottom.Weight == null)
          noWeightList.Enqueue(bottom);
        else
          noLivestockList.Enqueue(bottom);
      }


    }


    void BindTangGridFortangList()
    {
      VerifyConnection();
      if (connection)
      {
        try
        {
          tangList = GradeAndWeightRpc.GetGradeAndWeightList(butcherTimeInput.Date.Value, true);
        }
        catch (TimeoutException) { }
      }
      else
      {
        if (tangList == null)
          tangList = new List<GradeAndWeight>();
      }
    }


    void BindTangGrid()
    {
      tangGridView.DataSource = tangList.OrderBy(x => x.Order).OrderBy(x => x.Finish).ToList();
      if (tangEntity == null && tangGridView.CurrentRow != null)
      {
        tangEntity = tangGridView.CurrentRow.DataBoundItem as GradeAndWeight;
        //if (tangEntity.Finish)
        //  tangEntity = null;
      }
      foreach (DataGridViewRow row in tangGridView.Rows)
      {
        if ((bool)row.Cells["T_Finish"].Value)
          row.DefaultCellStyle.BackColor = Color.YellowGreen;
        if (tangEntity != null && tangEntity.OrderDetail_ID == (long)row.Cells["T_OrderDetail_ID"].Value)
        {
          tangEntity = row.DataBoundItem as GradeAndWeight;
          if (tangEntity.Finish)
            row.DefaultCellStyle.BackColor = Color.Yellow;
          else
            row.DefaultCellStyle.BackColor = tangGridView.RowsDefaultCellStyle.SelectionBackColor;
        }
      }
      InitTangScrollBar();
      tangGridView.ClearSelection();
      try
      {
        if (tangRoll != -1)
          tangGridView.FirstDisplayedScrollingRowIndex = tangRoll;
      }
      catch
      {
        tangRoll = -1;
      }
      tangGridView.Refresh();
      //     lblTangTui.Text= "烫褪" + "("+tangList.Sum(x=>x.Number)+")";
    }

    void BindMaoGridFromaoList()
    {
      VerifyConnection();
      if (connection)
      {
        try
        {
          if (butcherTimeInput.Date.HasValue)
          {
            maoList = GradeAndWeightRpc.GetGradeAndWeightList(butcherTimeInput.Date.Value, false);
          }

        }
        catch (TimeoutException) { }
      }
      else
      {
        if (maoList == null)
          maoList = new List<GradeAndWeight>();
      }
    }


    void BindMaoGrid()
    {

      maoGridView.DataSource = maoList.OrderBy(x => x.Order).OrderBy(x => x.Finish).ToList();
      if (maoEntity == null && maoGridView.CurrentRow != null)
      {
        maoEntity = maoGridView.CurrentRow.DataBoundItem as GradeAndWeight;
        //if (maoEntity.Finish)
        //  maoEntity = null;
      }
      foreach (DataGridViewRow row in maoGridView.Rows)
      {
        if ((bool)row.Cells["M_Finish"].Value)
          row.DefaultCellStyle.BackColor = Color.YellowGreen;
        if (maoEntity != null && maoEntity.OrderDetail_ID == (long)row.Cells["M_OrderDetail_ID"].Value)
        {
          maoEntity = row.DataBoundItem as GradeAndWeight;
          if (maoEntity.Finish)
            row.DefaultCellStyle.BackColor = Color.Yellow;
          else
            row.DefaultCellStyle.BackColor = maoGridView.RowsDefaultCellStyle.SelectionBackColor;
        }
      }
      InitMaoScrollBar();
      maoGridView.ClearSelection();
      try
      {
        if (maoRoll != -1)
          maoGridView.FirstDisplayedScrollingRowIndex = maoRoll;
      }
      catch
      {
        maoRoll = -1;
      }
      maoGridView.Refresh();
      //      lblMaoBo.Text = "毛剥" + "(" + maoList.Sum(x=>x.Number) + ")";
    }

    void BindDetailGrid()
    {
      historyGrid.DataSource = null;
      if (details.Any())
        historyGrid.DataSource = details;
      foreach (DataGridViewRow row in historyGrid.Rows)
      {
        if ((bool)row.Cells["H_IsDrop"].Value)
          row.DefaultCellStyle.BackColor = Color.Red;
      }
      InitScrollBar2();
      //if (lastSelectID.HasValue)
      //{
      //  foreach (DataGridViewRow row in historyGrid.Rows)
      //  {
      //    if ((long)row.Cells["H_SID"].Value == lastSelectID)
      //    {
      //      historyGrid.CurrentCell = row.Cells[row.Cells.Count - 1];
      //      break;
      //    }
      //  }
      //}
      try
      {
        if (rightRoll != -1)
          historyGrid.FirstDisplayedScrollingRowIndex = rightRoll;
      }
      catch
      {
        rightRoll = -1;
      }
      historyGrid.Refresh();
      //      SetHistorBackColor();
      //      ReSetHistorySum();
    }

    void StartPrintEntity(string gongyijibie, int? index)
    {
      if (!isPrintCheckBox.Checked)
      {
        return;
      }
      if (string.IsNullOrWhiteSpace(gongyijibie))
      {
        return;
      }
      var entity = CreatePrintEntity(gongyijibie, index);
      WeightGradePrint.Print(entity);
    }

    PrintEntity CreatePrintEntity(string jibie, int? index)
    {
      string goodsName;
      if (jibie == "烫褪")
      {
        goodsName = "带皮白条";
      }
      else
      {
        goodsName = "去皮白条";
      }

      var entity = new PrintEntity();
      entity.AccountingUnit_Name = "青岛万福集团股份有限公司";
      entity.Goods_Name = goodsName;
      entity.Date = DateTime.Today;
      entity.Checker = "";
      entity.StoreCondition = "0-4℃";
      entity.Place = "青岛莱西市";
      entity.TelNumber = "0532-88488888";

      int maxindex;
      if (index == null)
      {
        maxindex = LocalGradeAndWeightBL.GetTodayTotalCount(butcherTimeInput.Date.Value);
        maxindex++;
      }
      else
      {
        maxindex = index.Value;
      }

      string indexCode = maxindex.ToString("D6");

      entity.BarCode = string.Format("WF{0}{1:00000}", DateTime.Today.ToString("yyyyMMdd"), indexCode);
      entity._2DQRCode = string.Format("http://www.bwpsoft.com?code={0}&name={1}", entity.BarCode, goodsName);

      return entity;
    }

    private void printBtn_Click(object sender, EventArgs e)
    {
      if (modifyDetail == null)
      {
        return;
      }
      StartPrintEntity(modifyDetail.Technics_Name, modifyDetail.Index);
      modifyDetail = null;
      modifyPanel.Hide();
    }

    //    void Print(object obj)
    //    {
    //      var entity = obj as PrintEntity;
    //      this.Invoke(new Action(() =>
    //      {
    //        WeightGradePrint.Print(entity);
    //      }));
    //    }



    private void configBtn_Click(object sender, EventArgs e)
    {
      new GradeSettingFrom().ShowDialog();
    }

    GradeAndWeight tangEntity;
    GradeAndWeight maoEntity;

    #region weightNeed
    void OpenSerialPort()
    {
      if (enableWeight.Checked)
        return;
      if (GradeContext.Config.RateSet == null)
        throw new Exception("请先配置称相关信息");

      weightPort.PortName = GradeContext.Config.ComSet;
      weightPort.BaudRate = GradeContext.Config.RateSet.Value;
      weightPort.DataBits = GradeContext.Config.BitSet.Value;
      weightPort.ReadBufferSize = 4096 * 100;
      if (!string.IsNullOrEmpty(GradeContext.Config.Format))
        format = "{0:{format}}".Replace("{format}", GradeContext.Config.Format);

      switch (GradeContext.Config.WeightSet)
      {
        case "IND560":
          _dataFormat = new IND560DataFormat();
          break;
        case "Xk3124":
          _dataFormat = new Xk3124DataFormat();
          break;
        case "Xk3190A9":
          _dataFormat = new Xk3190A9DataFormat();
          break;
        default:
          _dataFormat = new Xk3190D10DataFormat();
          break;
      }
      if (!weightPort.IsOpen)
      {
        try
        {
          weightPort.Open();
        }
        catch (InvalidOperationException)
        {
          MessageBox.Show(@"指定的端口已打开");
        }
        catch (UnauthorizedAccessException)
        {
          MessageBox.Show(@"对端口的访问被拒绝");
        }
      }
    }

    void ReadData()
    {
      _inQueryThread = new Thread(InQuery);
      _inQueryThread.Start();
    }

    string format = "{0:0.00}";

    private DateTime lastWeightDateTime = DateTime.Now;

    private void InQuery()
    {
      while (_mainProcessIsRun)
      {
        int availableCount = weightPort.BytesToRead;
        if (availableCount == 0)
        {
          Thread.Sleep(1);
        }
        char[] buffer = new char[availableCount];
        if (!weightPort.IsOpen)
        {
          continue;
        }
        weightPort.Read(buffer, 0, availableCount);
        foreach (var c in buffer)
        {
          if (c == _dataFormat.Beginchar)
          {
            _dataStrBuilder.Clear();
            _dataStrBuilder.Append(c);
          }
          else if (c == _dataFormat.Endchar && _dataStrBuilder.Length == _dataFormat.DataLength - 1)
          {
            _dataStrBuilder.Append(c);
            bool isStatic;
            string str;
            if (_dataFormat.ParseAscii(_dataStrBuilder.ToString(), out str, out isStatic))
            {
              //稳定后发送
              if (GradeContext.Config.WeightType == 0)
              {
                if (string.IsNullOrEmpty(str))
                  str = "0";
                this.Invoke(new InvokeHandler(delegate()
                {
                  lblChengZhong.Text = string.Format(format, decimal.Parse(str));
                  if (str != "0")
                  {
                    //稳定发送有效间隔
                    var allowInterval = GradeContext.Config.AllowInterval;
                    //如果间隔时间内多条的话不处理

                    //                    var timeSpanTotalSeconds= (DateTime.Now - lastWeightDateTime).TotalSeconds;
                    //                    if (Convert.ToDecimal(timeSpanTotalSeconds) > allowInterval)
                    //                    {
                    AddWeightDetail(decimal.Parse(lblChengZhong.Text));
                    //                      lastWeightDateTime = DateTime.Now;
                    //                    }

                  }
                }));
              }
              //连续发送
              else
              {
                decimal num = 0;
                if (decimal.TryParse(str, out num))
                {
                  this.Invoke(new InvokeHandler(delegate()
                  {
                    lblChengZhong.Text = string.Format(format, num);
                  }));
                  LocalGradeAndWeightBL.SaveWeightData(num);
                  WeighAvgControl.Add(num, isStatic);
                }
                if (WeighAvgControl.TryGetValue(out num))
                {
                  this.Invoke(new InvokeHandler(delegate()
                  {
                    //lblChengZhong.Text = string.Format(format, num);
                    if (str != "0")
                    {
                      //
                      AddWeightDetail(decimal.Parse(string.Format(format, num)));
                    }
                  }));
                }
              }
            }
            _dataStrBuilder.Clear();
          }
          else if (_dataStrBuilder.Length != 0)
          {
            _dataStrBuilder.Append(c);
          }
        }
      }
    }

    private class WeighAvgControl
    {
      public static bool TryGetValue(out decimal result)
      {
        List<Tuple<decimal, bool>> list;
        if (mWeighList.TryDequeue(out list))
        {
          var r = list.Where(x => x.Item2).Select(x => x.Item1).GroupBy(x => x);
          var firstOrDefault = r.OrderByDescending(x => x.Count()).FirstOrDefault();
          if (firstOrDefault != null)
          {
            result = firstOrDefault.Key;
            return true;
          }
          result = 0;
          return false;
        }
        result = 0;
        return false;
      }

      static ConcurrentQueue<List<Tuple<decimal, bool>>> mWeighList = new ConcurrentQueue<List<Tuple<decimal, bool>>>();

      static List<Tuple<decimal, bool>> _list = new List<Tuple<decimal, bool>>();

      public static void Add(decimal value, bool isStatic)
      {
        if (value >= GradeContext.Config.MinWeight && value <= GradeContext.Config.MaxWeight)
        {
          _list.Add(new Tuple<decimal, bool>(value, isStatic));
        }
        else
        {
          if (_list.Count > 0)
          {
            mWeighList.Enqueue(_list);
            _list = new List<Tuple<decimal, bool>>();
          }
        }
      }
    }

    void DisableWeight()
    {
      _mainProcessIsRun = false;
      lblChengZhong.Text = string.Format(format, 0);
      format = "{0:0.00}";
      Thread.Sleep(10);
      if (_inQueryThread.IsAlive)
      {
        _inQueryThread.Abort();
      }
      if (weightPort.IsOpen)
        weightPort.Close();
    }

    public void btnStartWeight_Click(object sender, EventArgs e)
    {
      if (details == null)
      {
        MessageBox.Show("请先同步数据");
        return;
      }
      btnStartWeight.Enabled = false;
      OpenSerialPort();
      _mainProcessIsRun = true;
      ReadData();

      btnStopWeight.Enabled = true;


    }
    public void btnStopWeight_Click(object sender, EventArgs e)
    {
      btnStartWeight.Enabled = true;
      DisableWeight();
      btnStopWeight.Enabled = false;
    }

    public void enableWeight_Click(object sender, EventArgs e)
    {
      if (details == null)
      {
        MessageBox.Show("请先同步数据");
        return;
      }
      if (!enableWeight.Checked)
      {
        OpenSerialPort();
        _mainProcessIsRun = true;
        ReadData();
      }
      else
        DisableWeight();
      enableWeight.CheckState = enableWeight.Checked ? CheckState.Unchecked : CheckState.Checked;
    }
    #endregion

    static object _obj = new object();


    //    void AddDetail(CTuple<long, string, short, string> livestock)
    //    {
    //      lock (_obj)
    //      {
    //        var currentRow = livestock.Item3 == 0 ? tangEntity : maoEntity;
    //        var tech = livestock.Item3 == TANG_TECH ? "烫褪" : "毛剥";
    //
    //        GradeAndWeight_Detail first;
    //        if (noLivestockList.TryPeek(out first) && first.Livestock_ID == null)
    //        {
    //          noLivestockList.TryDequeue(out first);
    //          if (currentRow != null)
    //            first.OrderDetail_ID = currentRow.OrderDetail_ID;
    //          first.Date = butcherTimeInput.Date.Value;
    //          first.Livestock_ID = livestock.Item1;
    //          first.Livestock_Name = livestock.Item2;
    //          first.Technics = livestock.Item3;
    //          first.Technics_Name = tech;
    //          if (disBtn != null)
    //          {
    //            first.Weight = (first.Weight ?? 0) - Convert.ToDecimal(disBtn.Tag);
    //            SetBtnUnCheck(disBtn);
    //            disBtn = null;
    //          }
    //          LocalGradeAndWeightBL.Update(first, "OrderDetail_ID", "Date", "Livestock_ID", "Livestock_Name", "Technics", "Technics_Name", "Weight");
    //          historyGrid.Refresh();
    //        }
    //        else//add
    //        {
    //          maxIndex++;
    //          var entity = new GradeAndWeight_Detail();
    //          entity.Index = maxIndex;
    //          if (currentRow != null)
    //            entity.OrderDetail_ID = currentRow.OrderDetail_ID;
    //          entity.Date = butcherTimeInput.Date.Value;
    //          entity.Livestock_ID = livestock.Item1;
    //          entity.Livestock_Name = livestock.Item2;
    //          entity.Technics = livestock.Item3;
    //          entity.Technics_Name = tech;
    //          entity.Time = DateTime.Now;
    //          entity.Date = butcherTimeInput.Date.Value;
    //          if (disBtn != null)
    //          {
    //            entity.Weight = -Convert.ToDecimal(disBtn.Tag);
    //            SetBtnUnCheck(disBtn);
    //            disBtn = null;
    //          }
    //          if (details.Count == 50)
    //            details.RemoveAt(49);
    //          details.Insert(0, entity);
    //          LocalGradeAndWeightBL.Insert(entity);
    //          noWeightList.Enqueue(entity);
    //          BindDetailGrid();
    //        }
    //        if (currentRow != null)
    //        {
    //          currentRow.Already = currentRow.Already + 1;
    //          orderLabel.Text = currentRow.Order.ToString();
    //          alreadyLabel.Text = currentRow.Already.ToString();
    //          tangGridView.Refresh();
    //        }
    //        else
    //        {
    //          orderLabel.Text = string.Empty;
    //          alreadyLabel.Text = string.Empty;
    //        }
    //
    //        //计算合计
    //        ReSetHistorySum();
    //      }
    //    }

    //点级别
    void AddDetail(CTuple<long, string, short, string> livestock)
    {
      lock (_obj)
      {
        var n = 0;
        var currentRow = livestock.Item3 == 0 ? tangEntity : maoEntity;
        var tech = livestock.Item3 == TANG_TECH ? "烫褪" : "毛剥";

        GradeAndWeight_Detail first;
        //TryPeek 尝试返回 ConcurrentQueue<T> 开头处的对象但不将其移除
        //TryDequeue 尝试移除并返回并发队列开头处的对象。
        if (noLivestockList.TryDequeue(out first))
        {
          if (currentRow != null)
          {
            first.OrderDetail_ID = currentRow.OrderDetail_ID;
            first.Order = currentRow.Order;
            n = currentRow.Already;
          }
          first.Date = butcherTimeInput.Date.Value;
          first.Livestock_ID = livestock.Item1;
          first.Livestock_Name = livestock.Item2;
          first.Technics = livestock.Item3;
          first.Technics_Name = tech;
          if (disBtn != null)
          {
            first.Weight = (first.Weight ?? 0) - Convert.ToDecimal(disBtn.Tag);
            SetBtnUnCheck(disBtn);
            disBtn = null;
          }
          LocalGradeAndWeightBL.Update(first, "OrderDetail_ID", "Order", "Date", "Livestock_ID", "Livestock_Name", "Technics", "Technics_Name", "Weight");
          historyGrid.Refresh();
        }
        else//add  
        {
          maxIndex++;
          var entity = new GradeAndWeight_Detail();
          entity.Index = maxIndex;
          if (currentRow != null)
          {
            entity.OrderDetail_ID = currentRow.OrderDetail_ID;
            entity.Order = currentRow.Order;
            n = currentRow.Already;
          }
          entity.Date = butcherTimeInput.Date.Value;
          entity.Livestock_ID = livestock.Item1;
          entity.Livestock_Name = livestock.Item2;
          entity.Technics = livestock.Item3;
          entity.Technics_Name = tech;
          entity.Time = DateTime.Now;
          entity.Date = butcherTimeInput.Date.Value;
          if (disBtn != null)
          {
            entity.Weight = -Convert.ToDecimal(disBtn.Tag);
            SetBtnUnCheck(disBtn);
            disBtn = null;
          }
          //如果手动点击新增明细，则明细的重量=0
          entity.Weight = 0;
          entity.IsLostWeight = true;

          if (details.Count == 50)
            details.RemoveAt(49);
          details.Insert(0, entity);
          //          LocalGradeAndWeightBL.Insert(entity); 改成调用方法 方便加锁
          LocalGradeAndWeightBLInsert(entity);
          //          noWeightList.Enqueue(entity); // 添加的掉猪明细不加入到没有称重队列


          //这里绑定界面 东旭说不应该放到锁了 不知道怎么改
          BindDetailGrid();

        }


        if (currentRow != null)
        {
          currentRow.Already = n + 1;
          orderLabel.Text = currentRow.Order.ToString();
          alreadyLabel.Text = currentRow.Already.ToString();
          if (tech == "烫褪")
            tangGridView.Refresh();
          else
            maoGridView.Refresh();
        }
        else
        {
          orderLabel.Text = string.Empty;
          alreadyLabel.Text = string.Empty;
        }

        //计算合计
        //        ReSetHistorySum();
      }
    }

    static object insertweightdetail = new object();
    void LocalGradeAndWeightBLInsert(GradeAndWeight_Detail entity)
    {
      //为了防止点级别和称重同时进行
      lock (insertweightdetail)
      {
        LocalGradeAndWeightBL.Insert(entity);
      }
    }

    void SetlblSucessVisibleFalse()
    {
      this.Invoke(new InvokeHandler(delegate
      {
        Thread.Sleep(1000);
        lblSucessed.Visible = false;
      }));
    }

    void SetlblSucessVisibleTrue()
    {
      this.Invoke(new InvokeHandler(delegate
      {
        lblSucessed.Visible = true;
        Application.DoEvents();
      }));
    }


    //    void ReSetHistorySum()
    //    {
    //      var tangtui=LocalGradeAndWeightBL.GetTangTuiSumNumber(butcherTimeInput.Date.Value);
    //      var maobo=LocalGradeAndWeightBL.GetMaoBoSumNumber(butcherTimeInput.Date.Value);
    //      lblHeJi.Text = "合计：  烫褪（"+ tangtui + "）  毛剥（"+maobo+"）";
    //    }


    void AddWeightDetail(decimal weight)
    {
      lock (_obj)
      {
        weight -= (GradeContext.Config.Discont ?? 0);
        //        GradeAndWeight_Detail first;
        //        if (noWeightList.TryPeek(out first))
        //        {
        //          noWeightList.TryDequeue(out first);
        //          if (first.Weight < 0)
        //            first.Weight = (first.Weight ?? 0) + weight;
        //          else
        //            first.Weight = weight;
        //          LocalGradeAndWeightBL.Update(first, "Weight");
        //          historyGrid.Refresh();
        //        }
        //        else//add
        {


          maxIndex++;
          var entity = new GradeAndWeight_Detail();
          entity.Index = maxIndex;
          entity.Weight = (entity.Weight ?? 0) + weight;
          entity.Time = DateTime.Now;
          entity.Date = butcherTimeInput.Date.Value;
          if (details.Count == 50)
            details.RemoveAt(49);
          details.Insert(0, entity);

          //LocalGradeAndWeightBL.Insert(entity); //改成调用方法 方便加锁
          LocalGradeAndWeightBLInsert(entity);

          noLivestockList.Enqueue(entity);


          //          SetlblSucessVisibleTrue();
          //          SetlblSucessVisibleFalse();

        }
      }

      BindDetailGrid();
    }

    private void cancelBtn_Click(object sender, EventArgs e)
    {
      modifyDetail = null;
      modifyPanel.Hide();
    }


    //删除选中
    private void btnDeleteSelected_Click(object sender, EventArgs e)
    {
      if (MessageBox.Show("确定删除选中一条称重记录？", "删除选中", MessageBoxButtons.OKCancel) == DialogResult.Cancel)
      {
        return;
      }

      if (lastCheckItem == null)
      {
        return;
      }
      //如果没有选中
      if (!lastCheckItem.ReadWeight)
      {
        return;
      }
      //删除选中  更新 IsDeleted 和 Sync
      lastCheckItem.IsDeleted = true;
      LocalGradeAndWeightBL.Update(lastCheckItem, "IsDeleted");
      if (lastCheckItem.Order.HasValue)
      {
        if (lastCheckItem.Technics == 0)
        {
          foreach (DataGridViewRow row in tangGridView.Rows)
          {
            if ((int)row.Cells["T_Order"].Value == lastCheckItem.Order.Value)
            {
              var r = row.DataBoundItem as GradeAndWeight;
              r.Already -= 1;
              tangGridView.Refresh();
              break;
            }
          }
        }
        else
        {
          foreach (DataGridViewRow row in maoGridView.Rows)
          {
            if ((int)row.Cells["M_Order"].Value == lastCheckItem.Order.Value)
            {
              var r = row.DataBoundItem as GradeAndWeight;
              r.Already -= 1;
              maoGridView.Refresh();
              break;
            }
          }
        }
      }

      //修改本地
      if (lastCheckItem.OrderDetail_ID.HasValue)
      {
        VerifyConnection();
        if (!connection)
        {
          //"烫褪" : "毛剥"
          if (lastCheckItem.Technics_Name == "烫褪")
          {
            localTang = XmlUtil.DeserializeFromFile<List<long>>(tangFilePath);
            if (localTang.Contains(lastCheckItem.OrderDetail_ID.Value))
            {
              localTang.Remove(lastCheckItem.OrderDetail_ID.Value);
              SaveEntityToLocal(true);
            }
          }
          else if (lastCheckItem.Technics_Name == "毛剥")
          {
            localMao = XmlUtil.DeserializeFromFile<List<long>>(maoFilePath);
            if (localMao.Contains(lastCheckItem.OrderDetail_ID.Value))
            {
              localMao.Remove(lastCheckItem.OrderDetail_ID.Value);
              SaveEntityToLocal(false);
            }
          }
        }
      }

      details.Remove(lastCheckItem);


      //找到锁定的最大id
      long suodingmaxsid = 0;
      var lostweightlist = details.Where(x => x.IsLostWeight).ToList();
      if (lostweightlist.Count > 0)
      {
        suodingmaxsid = lostweightlist.Max(x => x.SID);
      }

      //重新赋值 队列
      //重新设置没有级别的
      noLivestockList = new ConcurrentQueue<GradeAndWeight_Detail>();
      var stackNoLiveStock = new Stack<GradeAndWeight_Detail>();

      //把没有级别的记录加进去
      var livestockNoNameList = details.Where(x => string.IsNullOrWhiteSpace(x.Livestock_Name));
      foreach (var item in livestockNoNameList)
      {
        if (item.SID > suodingmaxsid)
        {
          stackNoLiveStock.Push(item);
        }
      }
      while (stackNoLiveStock.Count > 0)
      {
        noLivestockList.Enqueue(stackNoLiveStock.Pop());
      }


      //重新设置没有重量的

      noWeightList = new ConcurrentQueue<GradeAndWeight_Detail>();
      var stackNoWeight = new Stack<GradeAndWeight_Detail>();


      //把没有重量的记录加进去
      var noWeightDetails = details.Where(x => x.Weight == null);
      foreach (var item in noWeightDetails)
      {
        if (item.SID > suodingmaxsid)
        {
          stackNoWeight.Push(item);
        }
      }
      while (stackNoWeight.Count > 0)
      {
        noWeightList.Enqueue(stackNoWeight.Pop());
      }



    }
    private void btnClearLastWeight_Click(object sender, EventArgs e)
    {

      if (MessageBox.Show("确定删除最后一条称重记录？", "删除称重", MessageBoxButtons.OKCancel) == DialogResult.Cancel)
      {
        return;
      }

      //      if (mCurrentSlectItem == null)
      //      {
      //        return;
      //      }


      #region 原来逻辑 清空最后一条有重量的值
      //      //有称重重量的 并且不是掉猪的最大的一条
      //      var fuhemaxsid = details.Where(x => x.Weight.HasValue && !x.IsLostWeight).Max(x => x.SID);
      //      var fd = details.First(x => x.SID == fuhemaxsid);
      //      fd.Weight = null;
      //
      //      //清空数据库重量记录
      //      LocalGradeAndWeightBL.ClearWeightBySID(fuhemaxsid);


      //      historyGrid.Refresh();
      //
      //      noWeightList = new ConcurrentQueue<GradeAndWeight_Detail>();
      //      var stack = new Stack<GradeAndWeight_Detail>();
      //      foreach (var item in details)
      //      {
      //        if (item.SID > fd.SID)
      //        {
      //          stack.Push(item);
      //        }
      //      }
      //      while (stack.Count > 0)
      //      {
      //        noWeightList.Enqueue(stack.Pop());
      //      }
      #endregion

      if (details.Count == 0)
      {
        return;
      }
      var lastItem = details[0];
      //如果级别不为空 则返回
      if (!string.IsNullOrWhiteSpace(lastItem.Livestock_Name))
      {
        return;
      }

      details.RemoveAt(0);
      //删除数据库
      LocalGradeAndWeightBL.DeleteBySID(lastItem.SID);
      historyGrid.Rows[0].Selected = true;
      historyGrid.FirstDisplayedScrollingRowIndex = 0;
      vScrollBar2.Value = 0;
      historyGrid.Refresh();



      //从新赋值 没有级别的
      //      noLivestockList=new ConcurrentQueue<GradeAndWeight_Detail>();
      //
      //
      //
      //      GradeAndWeight_Detail first;
      //      if (noLivestockList.TryPeek(out first) && first.Livestock_ID == null)
      //      {
      //        noLivestockList.TryDequeue(out first);
      //      }

      //重新设置没有级别的
      noLivestockList = new ConcurrentQueue<GradeAndWeight_Detail>();
      var stack = new Stack<GradeAndWeight_Detail>();

      //找到锁定的最大id
      long suodingmaxsid = 0;
      var lostweightlist = details.Where(x => x.IsLostWeight).ToList();
      if (lostweightlist.Count > 0)
      {
        suodingmaxsid = lostweightlist.Max(x => x.SID);
      }
      //把没有级别的记录加进去
      var livestockNoNameList = details.Where(x => string.IsNullOrWhiteSpace(x.Livestock_Name));
      foreach (var item in livestockNoNameList)
      {
        if (item.SID > suodingmaxsid)
        {
          stack.Push(item);
        }
      }
      while (stack.Count > 0)
      {
        noLivestockList.Enqueue(stack.Pop());
      }
    }

    private void btnLockItem_Click(object sender, EventArgs e)
    {
      if (mCurrentSlectItem == null)
      {
        return;
      }
      //获取最大值
      var lostList = details.Where(x => x.IsLostWeight).ToList();
      if (lostList.Count < 1)
      {
        maxLockID = 0;
      }
      else
      {
        maxLockID = lostList.Max(x => x.SID);
      }

      //赋最大值
      if (mCurrentSlectItem.SID > maxLockID)
      {
        maxLockID = mCurrentSlectItem.SID;
        UpdateItemLosted(mCurrentSlectItem.SID);

        if (modifyPanel.Visible)
          modifyPanel.Hide();
        historyGrid.Refresh();

        noWeightList = new ConcurrentQueue<GradeAndWeight_Detail>();
        var stack = new Stack<GradeAndWeight_Detail>();
        foreach (var item in details)
        {
          if (item.SID > mCurrentSlectItem.SID)
          {
            stack.Push(item);
          }
        }
        while (stack.Count > 0)
        {
          noWeightList.Enqueue(stack.Pop());
        }

      }
      //      SetHistorBackColor();


    }

    //    void SetHistorBackColor()
    //    {
    //      foreach (DataGridViewRow row in historyGrid.Rows)
    //      {
    //        if ((bool)row.Cells["IsLostWeight"].Value)
    //          row.DefaultCellStyle.ForeColor = Color.Red;
    //      }
    //    }

    private void UpdateItemLosted(long sid)
    {
      //设置数据库
      LocalGradeAndWeightBL.UpdateLosted(sid);

      //更新界面
      var fd = details.First(x => x.SID == sid);
      fd.IsLostWeight = true;
    }

    private long? maxLockID;

    GradeAndWeight_Detail lastCheckItem, mCurrentSlectItem;
    //long? lastSelectID = null;
    private void historyGrid_CellClick(object sender, DataGridViewCellEventArgs e)
    {
      if (e.RowIndex < 0)
        return;
      var currentRow = historyGrid.CurrentRow.DataBoundItem as GradeAndWeight_Detail;
      // lastSelectID = currentRow.SID;

      mCurrentSlectItem = currentRow;

      if (e.ColumnIndex == 4)
      {
        if (lastCheckItem != null && lastCheckItem.SID != currentRow.SID)
          lastCheckItem.ReadWeight = false;
        lastCheckItem = currentRow;
        lastCheckItem.ReadWeight = !lastCheckItem.ReadWeight;
        //
        modifyDetail = null;
        if (modifyPanel.Visible)
          modifyPanel.Hide();
        historyGrid.Refresh();
        //        if (lastCheckItem.ReadWeight)
        //        {
        //          noWeightList = new ConcurrentQueue<GradeAndWeight_Detail>();
        //          var stack = new Stack<GradeAndWeight_Detail>();
        //          foreach (var item in details)
        //          {
        //            if (item.SID > lastCheckItem.SID)
        //            {
        //              stack.Push(item);
        //            }
        ////            stack.Push(item);
        ////            if (item.SID == lastCheckItem.SID)
        ////              break;
        //          }
        //          while (stack.Count > 0)
        //            noWeightList.Enqueue(stack.Pop());
        //        }
        //        else
        //        {
        //          FillQueue();
        //          lastCheckItem = null;
        //        }
        return;
      }
      modifyDetail = currentRow;
      stateLabel.Text = string.Format("您正在修改序号为 {0} 的信息", modifyDetail.Index);
      modifyPanel.Show();
    }

    private void tangGridView_CellClick(object sender, DataGridViewCellEventArgs e)
    {
      if (e.RowIndex == -1)
        return;
      if (e.ColumnIndex == tangGridView.Columns.Count - 1)
        return;
      var entity = tangGridView.CurrentRow.DataBoundItem as GradeAndWeight;
      if (tangEntity != null)
      {
        foreach (DataGridViewRow row in tangGridView.Rows)
        {
          if (tangEntity.OrderDetail_ID == (long)row.Cells["T_OrderDetail_ID"].Value)
          {
            row.DefaultCellStyle.BackColor = tangEntity.Finish ? Color.YellowGreen : tangGridView.RowsDefaultCellStyle.BackColor;
            break;
          }
        }
      }
      tangEntity = entity;
      tangGridView.CurrentRow.DefaultCellStyle.SelectionBackColor = tangEntity.Finish ? Color.Yellow : tangGridView.RowsDefaultCellStyle.SelectionBackColor;
      tangGridView.Refresh();
    }

    private void tangGridView_CellContentClick(object sender, DataGridViewCellEventArgs e)
    {
      if (e.RowIndex == -1)
        return;
      if (e.ColumnIndex != tangGridView.ColumnCount - 1)
        return;
      var entity = tangGridView.CurrentRow.DataBoundItem as GradeAndWeight;
      if (entity.Finish)
      {
        tangEntity = null;
        return;
      }
      entity.Finish = true;
      VerifyConnection();
      if (connection)
        GradeAndWeightRpc.SetGradeFinish(entity.OrderDetail_ID, TANG_TECH);
      else
      {
        localTang = XmlUtil.DeserializeFromFile<List<long>>(tangFilePath);
        if (!localTang.Contains(entity.OrderDetail_ID))
        {
          localTang.Add(entity.OrderDetail_ID);
          SaveEntityToLocal(true);
        }
        var f = tangList.FirstOrDefault(x => x.OrderDetail_ID == entity.OrderDetail_ID);
        if (f != null)
          f.Finish = true;
      }
      tangEntity = null;
      BindTangGrid();
    }

    private void maoGridView_CellClick(object sender, DataGridViewCellEventArgs e)
    {
      if (e.RowIndex == -1)
        return;
      if (e.ColumnIndex == maoGridView.Columns.Count - 1)
        return;
      var entity = maoGridView.CurrentRow.DataBoundItem as GradeAndWeight;
      if (maoEntity != null)
      {
        foreach (DataGridViewRow row in maoGridView.Rows)
        {
          if (maoEntity.OrderDetail_ID == (long)row.Cells["M_OrderDetail_ID"].Value)
          {
            row.DefaultCellStyle.BackColor = maoEntity.Finish ? Color.YellowGreen : maoGridView.RowsDefaultCellStyle.BackColor;
            break;
          }
        }
      }
      maoEntity = entity;
      maoGridView.CurrentRow.DefaultCellStyle.SelectionBackColor = maoEntity.Finish ? Color.Yellow : maoGridView.RowsDefaultCellStyle.SelectionBackColor;
      maoGridView.Refresh();
    }

    private void maoGridView_CellContentClick(object sender, DataGridViewCellEventArgs e)
    {
      if (e.RowIndex == -1)
        return;
      if (e.ColumnIndex != maoGridView.ColumnCount - 1)
        return;
      var entity = maoGridView.CurrentRow.DataBoundItem as GradeAndWeight;
      if (entity.Finish)
      {
        maoEntity = null;
        return;
      }
      entity.Finish = true;
      VerifyConnection();
      if (connection)
        GradeAndWeightRpc.SetGradeFinish(entity.OrderDetail_ID, MAO_TECH);
      else
      {
        localMao = XmlUtil.DeserializeFromFile<List<long>>(maoFilePath);
        if (!localMao.Contains(entity.OrderDetail_ID))
        {
          localMao.Add(entity.OrderDetail_ID);
          SaveEntityToLocal(false);
        }
        var f = maoList.FirstOrDefault(x => x.OrderDetail_ID == entity.OrderDetail_ID);
        if (f != null)
          f.Finish = true;
      }
      maoEntity = null;
      BindMaoGrid();
    }

    private void discontBtn_Click(object sender, EventArgs e)
    {
      if (new BodyDiscontSetting().ShowDialog() == DialogResult.OK)
        BuildDiscontPanel(false);
    }

    Button disBtn = null;
    void BuildDiscontPanel(bool firstLoad)
    {
      var disconts = new List<BodyDiscontItem>();
      if (!firstLoad)
        VerifyConnection();
      if (connection)
      {
        disconts = GradeAndWeightRpc.GetBodyDiscontItem();
        XmlUtil.SerializerObjToFile(disconts, discontPath);
      }
      else
        disconts = XmlUtil.DeserializeFromFile<List<BodyDiscontItem>>(discontPath);

      disconts = disconts.Where(x => x.Discont > 0).OrderBy(x => x.ID).ToList();
      discontPanel.Controls.Clear();
      foreach (var item in disconts)
      {
        var btn = new Button() { Name = "_D" + item.ID, Text = item.Name, Tag = item.Discont, Size = new Size(70, 60), TextAlign = ContentAlignment.MiddleCenter, Margin = new Padding { Bottom = 30 }, Font = new Font("宋体", 15) };
        btn.Click += (sender, e) =>
        {
          if (modifyDetail == null)
          {
            //            if (disBtn != null)
            //              SetBtnUnCheck(disBtn);
            if (disBtn != btn)
            {
              disBtn = btn;
              //              SetBtnChecked(disBtn);
            }
            else
              disBtn = null;
          }
          else
          {
            modifyDetail.Weight = (modifyDetail.Weight ?? 0) - Convert.ToDecimal(btn.Tag);
            LocalGradeAndWeightBL.Update(modifyDetail, "Weight");
            historyGrid.Refresh();
            modifyDetail = null;
            modifyPanel.Hide();
          }
        };
        discontPanel.Controls.Add(btn);
      }
    }

    readonly Color btnSelectForeColor = Color.FromArgb(255, 255, 255);
    readonly Color btnSelectBackColor = Color.FromArgb(66, 163, 218);
    Color btnUnSelectForeColor = SystemColors.ControlText;
    Color btnUnSelectBackColor = Color.FromArgb(225, 225, 225);
    void SetBtnChecked(Button btn)
    {
      btn.BackColor = btnSelectBackColor;
      btn.ForeColor = btnSelectForeColor;
    }

    void SetBtnUnCheck(Button btn)
    {
      btn.BackColor = btnUnSelectBackColor;
      btn.ForeColor = btnUnSelectForeColor;
    }

    int tangRoll = -1;
    private void InitTangScrollBar()
    {
      tangScrollBar.Maximum = (tangGridView.RowCount - tangGridView.DisplayedRowCount(false) + 30) * tangGridView.RowTemplate.Height;
      tangScrollBar.Minimum = 0;
      tangScrollBar.SmallChange = tangGridView.RowTemplate.Height;
      tangScrollBar.LargeChange = tangGridView.RowTemplate.Height * 30;
      this.tangScrollBar.Scroll += (sender, e) =>
      {
        tangRoll = e.NewValue / tangGridView.RowTemplate.Height;
        tangGridView.FirstDisplayedScrollingRowIndex = tangRoll;
      };
    }

    int maoRoll = -1;
    private void InitMaoScrollBar()
    {
      maoScrollBar.Maximum = (maoGridView.RowCount - maoGridView.DisplayedRowCount(false) + 30) * maoGridView.RowTemplate.Height;
      maoScrollBar.Minimum = 0;
      maoScrollBar.SmallChange = maoGridView.RowTemplate.Height;
      maoScrollBar.LargeChange = maoGridView.RowTemplate.Height * 30;
      maoScrollBar.Scroll += (sender, e) =>
      {
        maoRoll = e.NewValue / maoGridView.RowTemplate.Height;
        maoGridView.FirstDisplayedScrollingRowIndex = maoRoll;
      };
    }

    int rightRoll = -1;
    private void InitScrollBar2()
    {
      vScrollBar2.Maximum = (historyGrid.RowCount - historyGrid.DisplayedRowCount(false) + 30) * historyGrid.RowTemplate.Height;
      vScrollBar2.Minimum = 0;
      vScrollBar2.SmallChange = historyGrid.RowTemplate.Height;
      vScrollBar2.LargeChange = historyGrid.RowTemplate.Height * 30;

      this.vScrollBar2.Scroll += (sender, e) =>
      {
        rightRoll = e.NewValue / historyGrid.RowTemplate.Height;
        historyGrid.FirstDisplayedScrollingRowIndex = rightRoll;
      };
    }

    object _fileSaveObj = new object();
    void SaveEntityToLocal(bool tang)
    {
      lock (_fileSaveObj)
      {
        if (tang)
          XmlUtil.SerializerObjToFile(localTang, tangFilePath);
        else
          XmlUtil.SerializerObjToFile(localMao, maoFilePath);
      }
    }

    void SyncLocalMainFinish(ref List<long> list, bool tang)
    {
      string path = maoFilePath;
      short tech = MAO_TECH;
      if (tang)
      {
        path = tangFilePath;
        tech = TANG_TECH;
      }

      list = XmlUtil.DeserializeFromFile<List<long>>(path);
      var count = list.Count;
      if (count == 0)
        return;
      if (count >= 30)
        count = 30;

      var sync = list.GetRange(0, count);
      foreach (var item in sync)
      {
        GradeAndWeightRpc.SetGradeFinish(item, tech);
        list.Remove(item);
      }
      SaveEntityToLocal(tang);
    }

    bool? last = null;
    void VerifyConnection()
    {
      connection = LoginRpcUtil.TestConnection();
      if (last == connection)
        return;
      var png = "stop.png";
      if (connection)
        png = "working.png";
      var imgPath = Path.Combine(Application.StartupPath, "BWP.WinFormControl.dll");
      var s = Assembly.LoadFile(imgPath).GetManifestResourceStream("BWP.WinFormControl.Images." + png);
      if (this.InvokeRequired)
      {
        this.BeginInvoke(new Action(() =>
        {
          statePic.Image = Image.FromStream(s);
          statePic.Refresh();
        }));
      }
      else
      {
        statePic.Image = Image.FromStream(s);
        statePic.Refresh();
      }

      last = connection;
    }

    private void btnAbnormalModify_Click(object sender, EventArgs e)
    {
      if (!butcherTimeInput.Date.HasValue)
      {
        MessageBox.Show("请在上一个界面选择宰杀日期");
        return;
      }
      var f = new AbnormalModifyForm(butcherTimeInput.Date.Value);
      f.ShowDialog();
    }

    private void GradeFrom_Load(object sender, EventArgs e)
    {
      syncToServer = new Thread(ToServerTask);
      syncToServer.Start();
    }

    void ToServerTask()
    {
      while (true)
      {
        //        this.Invoke(new InvokeHandler(delegate ()
        {
          VerifyConnection();
          if (connection)
          {
            try
            {
              SyncLocalMainFinish(ref localTang, true);
              SyncLocalMainFinish(ref localMao, false);
              SyncDiscontToSever();
              LocalGradeAndWeightBL.Sync();
            }
            catch (Exception ex)
            {
              File.WriteAllText(string.Format("{0:yyyyMMddHHmmss}log.txt", DateTime.Now), "错误：" + ex.Message + " \n详细信息：" + ex.StackTrace);
            }
          }
        }
        //        ));
        Thread.Sleep(2000);
      }
    }

    void SyncDiscontToSever()
    {
      var changeFlagPath = Path.Combine(GradeFrom.DATA_PATH, "DiscontsChanged.txt");
      bool existFile = File.Exists(changeFlagPath);
      if (existFile)
      {
        var list = XmlUtil.DeserializeFromFile<List<BodyDiscontItem>>(discontPath);
        var changes = new List<CTuple<long, decimal?>>();
        foreach (var item in list)
          changes.Add(new CTuple<long, decimal?>(item.ID, item.Discont));
        GradeAndWeightRpc.SaveBodyDiscontItem(changes);
        File.Delete(changeFlagPath);
      }
    }

    private void dropPigBtn_Click(object sender, EventArgs e)
    {
      if (modifyDetail == null)
      {
        UMessageBox.Show("请先选择要设置为掉猪的行", "错误");
        return;
      }
      else
      {
        modifyDetail.IsDrop = !modifyDetail.IsDrop;
        LocalGradeAndWeightBL.Update(modifyDetail, "IsDrop");
        BindDetailGrid();
        modifyDetail = null;
        modifyPanel.Hide();
      }
    }

    private void dataConfirmBtn_Click(object sender, EventArgs e)
    {
      new DataConfirm().ShowDialog();
    }
  }
}
