using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;


namespace Assets
{
    public class InputProcess: IDisposable
    {
        public String AppPath { get; set; }

        public int BufferSize { get; set; }

        private Queue MessageQueue { get;  set; }
        public ControllMessage LastMessage { get; private set; }
        public String LastLine { get; private set; }

        public ControllMessage LastValidSquare { get; set; }
        

        readonly object _messageQueueLock = new object();

        public InputProcess()
        {
            BufferSize = 50;
        }

        private Thread _readThread;
        private Process _process;

        bool shouldDie = false;

        ProcessStartInfo GetStartInfo()
        {
            ProcessStartInfo startInfo = new ProcessStartInfo(AppPath)
            {
                CreateNoWindow = true,
                ErrorDialog = false,
                RedirectStandardError = true,
                RedirectStandardInput = true,
                RedirectStandardOutput = true,
                UseShellExecute = false
            };

            startInfo.CreateNoWindow = true;
            return startInfo;
        }

        

        private void Read(StreamReader reader)
        {
            _readThread = new Thread(() =>
            {
                
                while (!shouldDie)
                {

                    var aLine = reader.ReadLine();


                    var aMessage = ControllMessage.FromString(aLine);

                    lock (_messageQueueLock)
                    {
                        LastLine = aLine;
                        LastMessage = aMessage;
                        MessageQueue.Enqueue(aMessage);
                        while (MessageQueue.Count > BufferSize)
                        {
                            MessageQueue.Dequeue();
                        }
                        if (aMessage != null && aMessage.Square != null)
                        {
                            LastValidSquare = aMessage;
                        }
                    }

                }

            });
            _readThread.Priority = ThreadPriority.AboveNormal;
            _readThread.Start();
        }

        public void Start()
        {
            MessageQueue = new Queue(BufferSize);

            _process = new Process {StartInfo = GetStartInfo()};
            _process.Start();


            Read(_process.StandardOutput);

        }


        public void Dispose()
        {
            if (_readThread != null && _readThread.IsAlive)
            {

                shouldDie = true;

                _process.Kill();

            }
        }

        public IEnumerable<ControllMessage> GetCurrentMessages()
        {
            lock (MessageQueue)
            {
                return MessageQueue.ToArray().Cast<ControllMessage>();
            }
        }
    }
}