using System;
using Microsoft.SPOT;

using System.Text;

namespace CPF
{
    public class StructQueue
    {
        //public delegate void qDelegate(qStruct inQStruct);

        public enum QRecordType : int
        {
            Optode = 0,
            SBE41,
            FLBB,
            ADC,
            PTH,
            InstrumentHandler,
            BTConsole,
            EVK7,
            IModem,
            StructQueue,
            WriteLog,
            PositionReport,
            MT_MessageArrived,
            FileReceived,
            FileSent,
            Error
        }

        public struct qStruct
        {
            public QRecordType 			qRecordType;
            public int 					errorCode;
            public DateTime 			timeStamp;
            public Program.CPFStates 	state;
            public byte[] 				byteArray;
        }

        private const int qDepth = 8192;
        public const int byteArrayWidth = 1024;

        private static qStruct[] queue;

        private static qStruct returnStruct;

        private static int head;
        private static int tail;
        private static int count;

        private static Object SQLock = new Object();

        private static StructQueue.qStruct qS = new StructQueue.qStruct();

        public StructQueue()
        {
            queue = new qStruct[qDepth];

            head = 0;
            tail = 0;
            count = 0;

            for (int i = 0; i < qDepth; i++)
                queue[i].byteArray = new byte[byteArrayWidth];

        }

        public int Count
        {
            get { return count; }
        }

        public void Clear()
        {
            count = 0;
            tail = head;
        }

        private static StringBuilder sbEnqueueErrorMsg = new StringBuilder("Enqueue Error: Queue full");
        public void Enqueue(qStruct inStruct)
        {
            lock (SQLock)
            {
                //GM I've taken out the ability to grow since if the queue does have to grow, something is wrong
                //if (count == qDepth)
                //{
                //  Grow();
                //}
                //queue[head] = value;
                if (count >= qDepth)
                {
                    //throw new InvalidOperationException("Queue is full");
                    ErrorHandler.incrEnqueueErrors();

                    qS.timeStamp = DateTime.Now;
                    qS.state = Program.CurrentState;
                    Array.Clear(qS.byteArray, 0, qS.byteArray.Length);
                    Array.Copy(UTF8Encoding.UTF8.GetBytes(sbEnqueueErrorMsg.ToString()), qS.byteArray, sbEnqueueErrorMsg.Length);
                    qS.qRecordType = StructQueue.QRecordType.StructQueue;
                    Program.sQueue.Enqueue(qS);
                }
                else
                {
                    queue[head].qRecordType = inStruct.qRecordType;
                    queue[head].timeStamp = inStruct.timeStamp;
                    queue[head].state = inStruct.state;
                    queue[head].errorCode = inStruct.errorCode;

                    Array.Copy(inStruct.byteArray, queue[head].byteArray, inStruct.byteArray.Length);
                    head = (head + 1) % qDepth;
                    count++;
                }
            }
        }

        public qStruct Dequeue()
        {
            lock (SQLock)
            {
                if (count == 0)
                {
                    throw new InvalidOperationException("Queue is empty");
                }
                else
                {
                    returnStruct = queue[tail];

                    //returnStruct.qRecordType = queue[tail].qRecordType;
                    //returnStruct.timeStamp = queue[tail].timeStamp;
                    //returnStruct.state = queue[tail].state;
                    //Array.Copy(queue[tail].byteArray, returnStruct.byteArray, queue[tail].byteArray.Length);

                    tail = (tail + 1) % qDepth;
                    count--;
                    return returnStruct;
                }
            }
        }
    }
}
