using System;
using System.Text;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

using Novell.CASA.MiCasa.Common;

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

		//public const int VERB_GET_SECRET = 1;
		//public const int VERB_SET_SECRET = 2;
		//public const int VERB_GET_KEYCHAIN = 3;
		//public const int VERB_GET_STORE = 4;
		//public const int VERB_SET_KEYVALUE = 5;
		//public const int VERB_GET_KEYVALUE = 6;
		public const int VERB_SET_LINKED_KEY = 7;
		public const int VERB_GET_LINKED_KEYS = 8;
		public const int VERB_REMOVE_LINKED_KEY = 9;
		public const int VERB_WRITE_KEY = 10;
		public const int VERB_REMOVE_ALL_SECRETS = 11;
		public const int VERB_LOCK_STORE = 12;
		public const int VERB_UNLOCK_STORE = 13;
		public const int VERB_GET_STORE_STATUS = 14;
		public const int VERB_REMOVE_KEY = 15;
		public const int VERB_READ_KEY = 16;
		public const int VERB_GET_KEY_LIST = 17;
		public const int VERB_RESET_MASTER_PASSWORD = 18;

		public const int VERB_DUMP_LINKED_KEYS = 96;
		public const int VERB_CREATE_TEST_SECRETS = 97;
		public const int VERB_REMOVE_TEST_SECRETS = 98;
		public const int VERB_PING_MICASAD = 99;

		public MiCasaRequestReply()
		{
			//
			// TODO: Add constructor logic here
			//
		}

		public static object Send(int verb)
		{
			return Send(verb, null, null, null, null);
		}

		public static object Send(int verb, object wo)
		{
			return Send(verb, null, null, null, wo);
		}

		public static object Send(int verb, 
			string sKeyChainID, 
			string sSecretID, 
			string sKeyID,
			object theObject)
		{

			// Lengths of message fields	
			int MSGID_LEN = 2;		
			int MSG_LEN = 4;
			WrappedObject request;
			WrappedObject reply = null;
						
			// open a client connection
			//IInterProcessConnection clientConnection = null;
			
			ClientChannel ipcChannel = IPCClientFactory.CreateClientConnection();			
			ipcChannel.Open();


			
			try 
			{						
				// contruct and serialize the Message Object
				request = new WrappedObject(verb, sKeyChainID, sSecretID, sKeyID, theObject);

				BinaryFormatter formatter = new BinaryFormatter();
				MemoryStream ms = new MemoryStream();
				formatter.Serialize(ms, request);
				ms.Flush();
				ms.Position = 0;	

				byte[] rawBytes = new byte[2+4+ms.Length];

				byte[] t = new byte[10];

				// set message id				
				int destIndex = 0;
				ushort msgId = 20;				
				t = BitConverter.GetBytes((ushort)msgId);
				Array.Copy(t,0,rawBytes,destIndex,MSGID_LEN);
				destIndex += MSGID_LEN;
						
				// set the object length
//Poorna
                int msgLen = 2+4+(int)ms.Length;
//              int msgLen = (int)ms.Length;
				t = BitConverter.GetBytes(msgLen);
//				t = BitConverter.GetBytes(ms.Length);
				Array.Copy(t,0,rawBytes,destIndex,MSG_LEN);
				destIndex += MSG_LEN;

				// copy in the object
				Array.Copy(ms.GetBuffer(), 0, rawBytes, destIndex, ms.Length);

				//clientConnection = new ClientPipeConnection("MyPipe", ".");
				//clientConnection = new ClientPipeConnection(XTIER_RPC_PIPE, ".");
				//clientConnection.Connect();
				
				// write the bytes
				//clientConnection.WriteBytes(rawBytes);
				ipcChannel.Write(rawBytes);				

				// read the bytes
				//byte[] returnBuffer = clientConnection.ReadBytes();
				byte[] returnBuffer = ipcChannel.Read();
				
				if (returnBuffer != null)
				{
					// deserialize MessageObject
					uint iMsgLen = BitConverter.ToUInt32(returnBuffer,0);
					ms = new MemoryStream(returnBuffer, 4, (int)iMsgLen);
					ms.Position = 0;
					reply = (WrappedObject)formatter.Deserialize(ms);				
					
					if (reply.GetReturnCode() != 0)
					{
						ipcChannel.Close();
						throw new Exception(reply.GetReturnCode().ToString());															
					}

				}

				// close the connection
				//clientConnection.Close();
				ipcChannel.Close();
				

			}
			catch (Exception e1)
			{
				Console.WriteLine(e1.ToString());
				//clientConnection.Dispose();				
				//throw new Exception(e1.ToString());
			}

			if (reply != null)
				return reply.GetObject();
			else
				return null;
		}
	}
	}