using BWP.WinFormControl;
using BWP.WinFormControl.WeightDataFormat;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ButcherWeight
{
  partial class WeightForm
  {
    private IDataFormat _dataFormat;
    private Thread _inQueryThread;
    private bool _mainProcessIsRun;
    readonly StringBuilder _dataStrBuilder = new StringBuilder();

    void OpenSerialPort()
    {
      if (enableCheckBox.Checked)
        return;
      if (WeightContext.Config.RateSet == null)
        throw new Exception("请先配置称相关信息");

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

      switch (WeightContext.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 (!weightSerialPort.IsOpen)
      {
        try
        {
          weightSerialPort.Open();
        }
        catch (InvalidOperationException)
        {
          MessageBox.Show(@"指定的端口已打开");
        }
        catch (UnauthorizedAccessException)
        {
          MessageBox.Show(@"对端口的访问被拒绝");
        }
      }
    }

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

    string format = "{0:0.00}";

    private void InQuery()
    {
      while (_mainProcessIsRun)
      {
        int availableCount = weightSerialPort.BytesToRead;
        if (availableCount == 0)
        {
          Thread.Sleep(1);
        }
        char[] buffer = new char[availableCount];
        if (!weightSerialPort.IsOpen)
        {
          continue;
        }
        weightSerialPort.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 (string.IsNullOrEmpty(str))
                str = "0";
              this.Invoke(new InvokeHandler(delegate()
              {
                weightLabel.Text = string.Format(format, decimal.Parse(str));
              }));
            }
            _dataStrBuilder.Clear();
          }
          else if (_dataStrBuilder.Length != 0)
          {
            _dataStrBuilder.Append(c);
          }
        }
      }
    }

    void DisableWeight()
    {
      _mainProcessIsRun = false;
      WeightValue = 0;
      format = "{0:0.00}";
      Thread.Sleep(10);
      if (_inQueryThread.IsAlive)
      {
        _inQueryThread.Abort();
      }
      if (weightSerialPort.IsOpen)
        weightSerialPort.Close();
    }

    public void enableCheckBox_Click(object sender, EventArgs e)
    {
      if (!enableCheckBox.Checked)
      {
        OpenSerialPort();
        _mainProcessIsRun = true;
        ReadData();
      }
      else
        DisableWeight();
      enableCheckBox.CheckState = enableCheckBox.Checked ? CheckState.Unchecked : CheckState.Checked;
      readMaoBtn.Enabled = readPiBtn.Enabled = enableCheckBox.Checked;
    }

    decimal? WeightValue
    {
      get
      {
        if (!string.IsNullOrEmpty(weightLabel.Text))
          return decimal.Parse(weightLabel.Text);
        return null;
      }
      set { weightLabel.Text = string.Format(format, value); }
    }
  }
}
