using System;
using System.Net;
using System.IO;
using System.Net.Sockets;
using Mono.Unix;

namespace Novell.CASA.MiCasa.Communication
{
    /// <summary>
    /// Summary description for UnixIPCClientChannel.
    /// </summary>
    public class UnixIPCClientChannel : ClientChannel
    {

        private Socket mSocket = null;
        private string socketFileName = "/tmp/.novellCASA";
        private EndPoint sockEndPoint;

        public UnixIPCClientChannel()
        {
        }

        public void Open()
        {
            mSocket = new Socket( AddressFamily.Unix,
                            SocketType.Stream,
                            ProtocolType.IP );

            if (mSocket == null) throw new Exception("could not get socket");
            sockEndPoint = new UnixEndPoint(socketFileName);
            mSocket.Connect(sockEndPoint);	 
        }

        public int Read(byte[] buf)
        {
            buf = Read();

            if (buf != null)
            {
                //Console.WriteLine("Bytes read = " + buf.Length);
                return buf.Length;
            }
            else
                return 0;
        }

        public byte[] Read()
        {
            byte[] returnBuffer = null;
            int bytesRecvd = 0;

            try
            {
                /* We need to read 'msgLen' to know how many bytes to
                 * allocate. 
                 */

                byte[] msgIdBytes = new byte[2];
                bytesRecvd = mSocket.Receive(msgIdBytes);
                if( 0 == bytesRecvd )
                {
                    return null;
                }
                byte[] msgLenBytes = new byte[4];
                bytesRecvd = mSocket.Receive(msgLenBytes);
                if( 0 == bytesRecvd )
                {
                    return null;
                }

                uint msgLen = BitConverter.ToUInt32(msgLenBytes,0);
                if( msgLen > 6 )
                {
                    byte[] buf = new byte[msgLen - 6];
                    bytesRecvd = mSocket.Receive (buf);
                    if( 0 == bytesRecvd )
                    {
                        return null;
                    }

                    returnBuffer = new byte[msgLen];
                    Array.Copy(msgIdBytes,returnBuffer,2);
                    Array.Copy(msgLenBytes,0,returnBuffer,2,4);
                    Array.Copy(buf,0,returnBuffer,6,buf.Length);
                    return returnBuffer;
                }
                else
                {
                    returnBuffer = new byte[6];
                    Array.Copy(msgIdBytes,returnBuffer,2);
                    Array.Copy(msgLenBytes,0,returnBuffer,2,4);
                    return returnBuffer;
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
                return null;
            }            
        }
        
        public int Write(byte[] buf)
        {
            try
            {
                mSocket.Send(buf);
                //Console.WriteLine("Bytes written = " + buf.Length);
                return buf.Length;
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
                return 0;
            }
        }

        public void Close()
        {
            mSocket.Close();        
        }
    }
}