using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;

using yoseen = YoseenSDKCS;

namespace YoseenDemoCustomDraw
{
    /// <summary>
    /// 温度画板, 演示了如何使用"GDI+ Graphics"显示温度数据
    /// </summary>
    public class TempCanvas : UserControl
    {
        TempCanvasConfig _config;

        public TempCanvas()
        {
            this.BackColor = Color.Gray;
            this.DoubleBuffered = true;

            _config = new TempCanvasConfig();
            _mea = yoseen.xxxmeasure.Create();
        }

        public int ChangeConfig(ushort dataWidth, ushort dataHeight)
        {
            int ret = _config.ChangeConfig(dataWidth, dataHeight);
            if (0 == ret)
            {
                this.Width = _config.OutputWidth;
                this.Height = _config.OutputHeight;
            }
            return ret;
        }

        yoseen.xxxmeasure _mea;
        yoseen.xxxresult _mresult;

        yoseen.DataFrameHeader _dfh;

        yoseen.DataFrame _dataFrame;
        public void UpdateData(ref yoseen.DataFrame dataFrame)
        {
            //只处理温度帧, 不处理视频帧
            if (dataFrame.Head == IntPtr.Zero) return;

            _hasData = true;
            _dataFrame = dataFrame;
            this.Invalidate();
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            //不处理单帧视频数据, 只处理单帧温度数据. 若确定开启的是温度流预览, 只会收到单帧温度, 此处无需判定.
            if (!_hasData) return;

            //复制位图数据到bmp
            Bitmap bmp = _config.Bmp;
            BitmapData bmpData = bmp.LockBits(_config.BmpSrcRect, ImageLockMode.WriteOnly, PixelFormat.Format32bppRgb);
            yoseen.Win32Helper.memcpy(bmpData.Scan0, _dataFrame.Bmp, _config.BmpDataSize);
            bmp.UnlockBits(bmpData);

            //提取特征温度
            yoseen.YoseenAlg.mtGetResult_GMO(_dataFrame.Head, _dataFrame.Temp, ref _mresult);
            string globalInfo = string.Format("GMax {0:F1}, GMin {1:F1}, GAvg {2:F1}; ({3}, {4}), ({5}, {6})",
                _mresult.max, _mresult.min, _mresult.avg, _mresult.maxX, _mresult.maxY, _mresult.minX, _mresult.minY);

            _dfh = (yoseen.DataFrameHeader)Marshal.PtrToStructure(_dataFrame.Head, typeof(yoseen.DataFrameHeader));

            //提取单点温度
            int x = 100, y = 200;
            float t = _config.GetXY(ref _dfh, _dataFrame.Temp, x, y);
            string localInfo = string.Format("t({0}, {1})={2:F1}", x, y, t);

            //开始绘制
            Graphics g = e.Graphics;
            g.DrawImage(bmp, _config.BmpDstRect);
            g.DrawString(globalInfo, TempCanvasConfig.Const_Font, TempCanvasConfig.Const_Brush, new PointF(50, 50));
            g.DrawString(localInfo, TempCanvasConfig.Const_Font, TempCanvasConfig.Const_Brush, new PointF(50, 100));
        }

        bool _hasData = false;
        public void BeginUpdate(int dw,int dh)
        {
            _hasData = false;
        }

        public void EndUpdate()
        {
            _hasData = false;
            this.Invalidate();
        }
    }

    /// <summary>
    /// 温度画板配置
    /// </summary>
    public class TempCanvasConfig
    {
        //静态绘制资源
        public static Font Const_Font = new Font("Times New Roman", 16);
        public static Brush Const_Brush = new SolidBrush(Color.Black);

        //数据分辨率相关配置
        public ushort DataWidth;
        public ushort DataHeight;

        public int OutputWidth;
        public int OutputHeight;

        public double Scale;

        public Bitmap Bmp;
        public Rectangle BmpSrcRect;
        public Rectangle BmpDstRect;
        public int BmpDataSize;

        //全局测温对象
        public yoseen.xxxrectangle MGlobal;

        public TempCanvasConfig()
        {
        }

        public int ChangeConfig(ushort dataWidth, ushort dataHeight)
        {
            if (DataWidth == dataWidth && DataHeight == dataHeight) return 0;
            if (dataWidth == 384 && dataHeight == 288)
            {
                //为了保证文本清晰，384x288使用640x480显示
                OutputWidth = 640; OutputHeight = 480;
                Scale = 640.0 / 384.0;
                BmpDstRect.Width = 640; BmpDstRect.Height = 480;
            }
            else if (dataWidth == 160 && dataHeight == 120)
            {
                //为了保证文本清晰，160x120使用640x480显示
                OutputWidth = 640; OutputHeight = 480;
                Scale = 640.0 / 160.0;
                BmpDstRect.Width = 640; BmpDstRect.Height = 480;
            }
            else
            {
                OutputWidth = dataWidth; OutputHeight = dataHeight;
                Scale = 1.0;
                BmpDstRect.Width = dataWidth; BmpDstRect.Height = dataHeight;
            }

            DataWidth = dataWidth;
            DataHeight = dataHeight;
            Bmp = new Bitmap(dataWidth, dataHeight, System.Drawing.Imaging.PixelFormat.Format32bppRgb);
            BmpSrcRect.Width = dataWidth; BmpSrcRect.Height = dataHeight;
            BmpDataSize = dataWidth * dataHeight * 4;

            //
            MGlobal.xmax = (ushort)(dataWidth - 1);
            MGlobal.ymax = (ushort)(dataHeight - 1);

            return 0;
        }

        /// <summary>
        /// 获取单点温度
        /// </summary>
        /// <param name="dfh"></param>
        /// <param name="ptrTemp"></param>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public float GetXY(ref yoseen.DataFrameHeader dfh, IntPtr ptrTemp, int x, int y)
        {
            IntPtr p = ptrTemp + (x + y * DataWidth) * 2;
            float t = Marshal.ReadInt16(p);
            t = t / dfh.Slope + dfh.Offset;
            return t;
        }

    }

    /// <summary>
    /// 温度数据更新委托
    /// </summary>
    /// <param name="dataFrame"></param>
    public delegate void DEL_UpdateData(yoseen.DataFrame dataFrame);
}
