using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Windows.Media.Imaging;
using System.IO.Ports;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using System.Windows.Threading;

namespace RemoteCamClient
{
    [NotifyPropertyChanged]
    public class MainViewModel
    {
        public bool IsLoading { get; set; }
        public int SizeToTransfer { get; set; }
        public int Transferred { get; set; }
        public int SignalStrength { get; set; }
        public BitmapSource BitmapSource { get; set; }

        private Dispatcher dispatcher;

        public MainViewModel(Dispatcher dispatcher)
        {
            this.dispatcher = dispatcher;
        }

        private XBee xbee;

        public void Start()
        {
            SerialPort port = new SerialPort("COM6", 115200);
            port.Open();
            xbee = new XBee(port);
        }

        public void GetImage()
        {
            IsLoading = true;
            Transferred = 0;
            Task.Factory.StartNew
                (() => RequestAndReceiveImage())
                .ContinueWith(
                    t => 
                        {
                            BitmapSource = FromBytes(t.Result);
                            IsLoading = false;
                        },
                    TaskScheduler.FromCurrentSynchronizationContext()
                );

        }

        private byte[] RequestAndReceiveImage()
        {
            byte[] imageData;
            byte[] b = { 66 };
            xbee.SendData(b);

            byte strength;
            byte[] length = xbee.ReceiveBinary(out strength);
            int imageSize = BitConverter.ToInt32(length, 0);
            dispatcher.BeginInvoke(
                new Action<int>(size => { SizeToTransfer = size; }), imageSize);
            imageData = new byte[imageSize];
            int received = 0;
            while (received < imageSize)
            {
                
                byte[] buffer = xbee.ReceiveBinary(out strength);
                Array.Copy(buffer, 0, imageData, received, buffer.Length);
                received += buffer.Length;
                dispatcher.BeginInvoke(
                    new Action<int, int>(
                        (r, s) => 
                        { 
                            Transferred = r;
                            SignalStrength = s;
                        }), received, strength);
            }
            return imageData;
        }

        private BitmapSource FromBytes(byte[] imageData)
        {
            BitmapImage bm = new BitmapImage();
            bm.BeginInit();
            System.Drawing.Bitmap bmi = new System.Drawing.Bitmap(new MemoryStream(imageData));
            MemoryStream ms = new MemoryStream();
            bmi.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
            ms.Seek(0, SeekOrigin.Begin);
            bm.StreamSource = ms;
            bm.EndInit();
            return bm;
        }
    }
}
