/*******************************************************************************
* 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.Globalization;
using System.Collections;

namespace RPCSupport.Pipelines
{
    public abstract class Pipeline 
    {
        public delegate void RawRpcRequest(string s);
        public delegate void RawRpcReply(string s);
        public delegate void RawRpcStream(string s);
        internal RawRpcRequest rawRpcRequest;
        internal RawRpcReply rawRpcReply;
        internal RawRpcStream rawRpcStream;
        public virtual bool Init()
        {
            return true;
        }

        public abstract string RawRpcCall(string request, bool reply);
        public abstract void SendSingleByte(char ch);
        public abstract void Discard();
        public abstract string RawRpcCallBinary(string request, bool reply, out bool allOnes);

        public void LogStream(string stream)
        {
            if (rawRpcStream != null)
            {
                rawRpcStream(stream);
            }
        }

        /*public virtual bool IsConnected()
        {
            return false;
        }*/
        public abstract bool IsConnected();

        public void LogCallback(RawRpcRequest request, RawRpcReply reply, RawRpcStream stream)
        {
            rawRpcRequest = request;
            rawRpcReply = reply;
            rawRpcStream = stream;
        }

        public String Call(string name, string method, params string[] args)
        {
            return SendRPC(name, method, args);
        }

        public String CallBinary(string name, string method, out bool allOnes, params string[] args)
        {
            return SendRPCBinary(name, method, out allOnes, args);
        }

        public String CallNoReply(string name, string method, params string[] args)
        {
            return SendRPCNoReply(name, method, args);
        }

        public virtual void Connect(string name)
        {
        }

        public virtual void Disconnect()
        {
        }

        public virtual String[] ScanAvailablePortNames()
        {
            return null;
        }

        public byte GetReturnValue_Byte()
        {
            return 0;
        }

        public String GetReturnValue()
        {
            return "";
        }

        private String TrimArgument(String str)
        {
            String strOut = "0";
            String strIn = str.TrimStart(new char[] { '0' });
            if (String.IsNullOrEmpty(strIn) == false)
            {
                strOut = strIn;
            }
            return strOut;
        }

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

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

            String request = "/" + Name + "/" + Method + Arguments + "\r\n";
            Console.WriteLine(request);
            String reply = RawRpcCall(request, true);

            return reply;
        }

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

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

            String request = "/" + Name + "/" + Method + Arguments + "\r\n";
            String reply = RawRpcCall(request, false);

            return reply;
        }

        public String SendRPCBinary(String Name, String Method, out bool allOnes, params String[] Args)
        {
            //write to serial port and receive result
            String Arguments = "";

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

            String request = "/" + Name + "/" + Method + Arguments + "\r\n";
            String reply = RawRpcCallBinary(request, false, out allOnes);

            return reply;
        }


        public byte StringToByte(String reply)
        {
            byte val = 0xFF;
            if (byte.TryParse(reply, NumberStyles.HexNumber, CultureInfo.CurrentCulture, out val))
            {
            }
            return val;
        }


        internal byte[] StringToMultiBytes(string reply, byte numBytes)
        {
            byte[] data = new Byte[numBytes];
            string[] strings = reply.Split(new char[] { ' ' });
            for (int i = 0; i < numBytes; i++)
            {
                data[i] = StringToByte(strings[i]);
            }
            return data;
        }

        public abstract string ReadString();
        public abstract int Read(char[] buffer, int offset, int count);
    }
}
