using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using TwinCAT.Ads;

namespace AdsImageWatch
{
    public partial class Form1 : Form
    {
        private TcAdsClient _adsClient;
        private TcAdsSymbolInfoLoader _symbolLoader;
        private List<TcAdsSymbolInfo> _symbolImagelist;

        private int hGetBitmapSize = 0;
        private int hGetBitmapImage = 0;
        public Form1()
        {
            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            _adsClient = new TcAdsClient();
        }
        private void button1_Click(object sender, EventArgs e)
        {
            _symbolImagelist = new List<TcAdsSymbolInfo>();

            if (textBox1.Text.Trim() != string.Empty)
                _adsClient.Connect(textBox1.Text, 851);
            else
                _adsClient.Connect(851);

            _symbolLoader = _adsClient.CreateSymbolInfoLoader();

            QueryImageResultSymbols();

        }

        private void QueryImageResultSymbols()
        {
            comboBox1.Items.Clear();
            foreach (TcAdsSymbolInfo symbol in _symbolLoader)
            {
                if (symbol.TypeName == "ITcVnDisplayableImage")
                {
                    _symbolImagelist.Add(symbol);
                    comboBox1.Items.Add(symbol.Name);
                }
            }
        }

        private void comboBox1_TextChanged(object sender, EventArgs e)
        {
            timer1.Stop();
            if (hGetBitmapSize != 0)
                _adsClient.DeleteVariableHandle(hGetBitmapSize);

            if(hGetBitmapImage !=0)
                _adsClient.DeleteVariableHandle(hGetBitmapImage);

            ComboBox cb = (ComboBox)sender;
            hGetBitmapSize = _adsClient.CreateVariableHandle(cb.Text +
                "#<<ITcVnBitmapExportRpcUnlocked>>GetBitmapSize");
            if (hGetBitmapSize != 0)
                hGetBitmapImage = _adsClient.CreateVariableHandle(cb.Text +
                "#<<ITcVnBitmapExportRpcUnlocked>>GetBitmapImageRpcUnlocked");

            timer1.Start();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            try
            {
                ReadImageData();
            }
            catch(Exception ex)
            {

            }

        }

        private void ReadImageData()
        {
            ImageInfo info = new ImageInfo();
            using (BinaryWriter writer = new BinaryWriter(new AdsStream(sizeof(uint) + sizeof(uint)))) // width + height
            using (BinaryReader reader = new BinaryReader(new AdsStream(sizeof(int) + sizeof(ulong) + sizeof(uint) +
            sizeof(uint)))) // hr + bitmapsize + width + height
            {
                writer.Write(info.nImageWidth);
                writer.Write(info.nImageHeight);
                long nOffs = _adsClient.ReadWrite((UInt32)AdsReservedIndexGroups.SymbolValueByHandle,
(UInt32)hGetBitmapSize, (AdsStream)reader.BaseStream, (AdsStream)writer.BaseStream);
                int hr = reader.ReadInt32();
                if ((hr & 0x80000000) != 0)
                    throw new System.ArgumentException("RpcCallFailed: LoadPictureError 0x" +
                    hr.ToString("X"));
                else
                {
                    info.nSrcImageSize = reader.ReadUInt64();
                    info.nSrcImageWidth = reader.ReadUInt32();
                    info.nSrcImageHeight = reader.ReadUInt32();
                }
            }
            info.bitmapBytes = new byte[info.nSrcImageSize];

            using (BinaryWriter writer = new BinaryWriter(new AdsStream(sizeof(ulong) + sizeof(uint) + sizeof(uint))))
            // size + width + height
            using (BinaryReader reader = new BinaryReader(new AdsStream(sizeof(int) + sizeof(ulong) +
            (int)info.nSrcImageSize + sizeof(uint) + sizeof(uint)))) // hr + bitmapsize + buffer size + width + height
            {
                writer.Write(info.nSrcImageSize);
                writer.Write(info.nImageWidth);
                writer.Write(info.nImageHeight);
                long nOffs = _adsClient.ReadWrite((UInt32)AdsReservedIndexGroups.SymbolValueByHandle,
                (UInt32)hGetBitmapImage, (AdsStream)reader.BaseStream, (AdsStream)writer.BaseStream);
                int hr = reader.ReadInt32();
                if ((hr & 0x80000000) != 0)
                    throw new System.ArgumentException("RpcCallFailed: LoadPictureError 0x" +
                    hr.ToString("X"));
                else
                {
                    info.nImageSize = reader.ReadUInt64();
                    info.bitmapBytes = reader.ReadBytes((int)info.nImageSize);
                    info.nImageWidth = reader.ReadUInt32();
                    info.nImageHeight = reader.ReadUInt32();

                    MemoryStream stream = new MemoryStream(info.bitmapBytes);
                    pictureBox1.BackgroundImage = new Bitmap((Image)new Bitmap(stream));
                   
                }
            }
        }

        private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
        {
        }
    }

    public class ImageInfo
    {
        // requested size
        public uint nImageWidth = 0;
        public uint nImageHeight = 0;
        // received values
        public ulong nSrcImageSize = 0;
        public ulong nImageSize = 0;
        public uint nSrcImageWidth = 0;
        public uint nSrcImageHeight = 0;
        public byte[] bitmapBytes = null;
    }

}
