/*******************************************************************************
* Copyright (C) 2016 Maxim Integrated Products, Inc., All rights Reserved.
* 
* This software is protected by copyright laws of the United States and
* of foreign countries. This material may also be protected by patent laws
* and technology transfer regulations of the United States and of foreign
* countries. This software is furnished under a license agreement and/or a
* nondisclosure agreement and may only be used or reproduced in accordance
* with the terms of those agreements. Dissemination of this information to
* any party or parties not specified in the license agreement and/or
* nondisclosure agreement is expressly prohibited.
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name of Maxim Integrated
* Products, Inc. shall not be used except as stated in the Maxim Integrated
* Products, Inc. Branding Policy.
*
* The mere transfer of this software does not imply any licenses
* of trade secrets, proprietary technology, copyrights, patents,
* trademarks, maskwork rights, or any other form of intellectual
* property whatsoever. Maxim Integrated Products, Inc. retains all
* ownership rights.
*******************************************************************************
*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;
using System.Diagnostics;
using RPCSupport.Pipelines;
using System.Threading;
using System.Collections;

using SerialWrap;

namespace RPCSupport
{
    public class SerialWrapPipeline : Pipeline {
	    protected SerialPortIo serialPortIo;
        SerialPortConfig serialPortConfig;

        public SerialWrapPipeline() 
        {
            //serialPort = new SerialPort();
	    }

        public int ReadTimeout
        {
            set
            {
                serialPortIo.ReadTimeout = value;
            }
            get
            {
                return serialPortIo.ReadTimeout;
            }
        }

        public override void Connect(String PortName)
        {
            serialPortConfig = new SerialPortConfig(PortName, 9600, 8, StopBits.One, Parity.None, true, true);

            /*
            // Set the read/write timeouts
            serialPort.ReadTimeout = 90000;
            serialPort.WriteTimeout = 90000;

            serialPort.PortName = PortName;
            serialPort.BaudRate = 9600;

            // always the same
            serialPort.DataBits = 8;
            serialPort.Parity = Parity.None;
            serialPort.StopBits = StopBits.One;
            serialPort.Handshake = Handshake.None;

            serialPort.DtrEnable = true;
            serialPort.RtsEnable = true;
            */

            serialPortIo = new SerialPortIo(serialPortConfig);

            serialPortIo.ReadTimeout = 1300;
            //Thread.Sleep(10);
            //serialPort.Open();

            //serialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived);
            //serialPort.ErrorReceived += new SerialErrorReceivedEventHandler(serialPort_ErrorReceived);
        }

        public override void Disconnect()
        {
            serialPortIo.Dispose();
        }

        public override bool IsConnected()
        {
            return serialPortIo.IsOpen;
        }

        public override String[] ScanAvailablePortNames()
        {
            return SerialPort.GetPortNames();
        }

        /*
	    public override String SendRPC(String Name, String Method, params String[] Args)
        {
		    //write to serial port and receive result
		    String Response;
		    String Arguments = "";

		    if(Args != null)
            {
			    for(int i = 0; i < Args.Length; i++)
                {
				    Arguments = Arguments + " " + Args[i];
			    }
		    }

            serialPort.DiscardInBuffer();
            String sendString = "/" + Name + "/" + Method + Arguments + "\r\n";
            String reply = RawRpcCall(sendString);

            return reply;
	    }*/

        /*
	    public override void delete()
        {
		    //Close the serial port
            if (serialPort != null) serialPort.Close();
        }
        */

        private void serialPort_DataReceived(object sender, EventArgs e)
        {
            Debug.Print("Serial Port event");
            //String Interrupt = serialPort.ReadLine();
            String str = serialPortIo.ReadExisting();
        }

        private void serialPort_ErrorReceived(object sender, EventArgs e)
        {
            Debug.Print("Serial Port error");
        }

        public override string RawRpcCall(string request, bool reply)
        {
            if (rawRpcRequest != null) rawRpcRequest(request);
            //String reply = myHID.RPC_Call(request);
            serialPortIo.WriteLine(request);
            if (reply == false) return "";

            string replyStr;
            replyStr = serialPortIo.ReadLine();
            if (rawRpcReply != null) rawRpcReply(replyStr);
            return replyStr;
        }

        public override void SendSingleByte(char ch)
        {
            char[] chArray = new char[1];
            chArray[0] = ch;
            serialPortIo.Write(chArray, 0, 1);
        }
        public override string ReadString()
        {
            return serialPortIo.ReadExisting();
        }
        public override int Read(char[] buffer, int offset, int count)
        {
            int val = 0;
            try
            {
                val = serialPortIo.Read(buffer, offset, count);
            }
            catch (Exception)
            {
            }
            return val;
        }
        public override void Discard()
        {
            serialPortIo.DiscardInBuffer();
        }

        public override string RawRpcCallBinary(string request, bool reply, out bool allOnes)
        {
            if (rawRpcRequest != null) rawRpcRequest(request);
            //String reply = myHID.RPC_Call(request);
            serialPortIo.WriteLine(request);
            //if (reply == false) return "";

            byte[] buffer = new byte[256];
            int bytesToRead = 256;
            while (bytesToRead != 0)
            {
                int bytesRead = serialPortIo.Read(buffer, 256 - bytesToRead, bytesToRead);
                bytesToRead -= bytesRead;
            }
            allOnes = true;
            for (int i = 0; i < 256; i++)
            {
                if (buffer[i] != 0xFF) allOnes = false;
            }
            string replyStr;
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < 256; i++)
            {
                sb.Append((buffer[i]).ToString("X2") + " ");
            }
            //replyStr = serialPort.ReadLine();
            replyStr = sb.ToString().Trim();
            String otherStr = serialPortIo.ReadLine();
            if (rawRpcReply != null) rawRpcReply(replyStr);
            return replyStr;
        }
    }
}
