/***********************************************************************
 * 
 *  Copyright (C) 2005-2006 Novell, Inc. All Rights Reserved.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; version 2.1
 *  of the License.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Library Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, Novell, Inc.
 * 
 *  To contact Novell about this file by physical or electronic mail, 
 *  you may find current contact information at www.novell.com.
 * 
 ***********************************************************************/

using System;
using System.Runtime.InteropServices;
using System.Collections.Specialized;
using System.Collections;


namespace Novell.CASA.DataEngines.FF
{
    
	[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
	public class Host
	{
		public IntPtr hostName;
		public IntPtr hostElement;
		public IntPtr next;
		/*public Host()
	//NOT NEEDED SINCE WE GET THIS FILLED FROM NATIVE WHEN
	//WE MARSHAL PTR TO STRUCTURE        
	{
			hostName = Marshal.AllocHGlobal(128);
		}
		~Host()
		{		
		try
		{ 
					Marshal.FreeHGlobal(hostName);
		}
		catch (Exception e)
		{
			Console.WriteLine("FireFox:Marshal FreeHGlobal Exception for Host:");		
		}
		}*/
	};


	[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
	public class HostElement
	{
		public IntPtr name;
		public IntPtr value;
		public int  isPassword;
		public IntPtr next;
		/*public HostElement()
		{
			name = Marshal.AllocHGlobal(128);
			value = Marshal.AllocHGlobal(128);
		}
		~HostElement()
		{
		try
		{ 
					Marshal.FreeHGlobal(name);
					Marshal.FreeHGlobal(value);
		}		
		catch (Exception e)
		{
					Console.WriteLine("FireFox:Marshal FreeHGlobal Exception for HostElement:");
		}
		}*/
	};


	[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
	public class KeyringInfo
	{
		public int lockOnIdle;
		public uint lockTimeout;
		public uint mTime;
		public uint cTime;
		public int isLocked;
	}
	[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
	public class NativeItemInfo
	{
		public int itemType;
		public IntPtr displayName;
		public IntPtr secret;
		public int mTime;
		public int cTime;
		public NativeItemInfo()
		{
			displayName = Marshal.AllocHGlobal(128);
			secret = Marshal.AllocHGlobal(128);
		}
		~NativeItemInfo()
		{
			Marshal.FreeHGlobal(displayName);
			Marshal.FreeHGlobal(secret);
		}
	}

	public class ItemInfo
	{
		public string itemType;
		public string displayName;
		public string secret;
		public int mTime;
		public int cTime;
	}


	[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
	public class NativeAttribute
	{
		public uint type;
		public IntPtr key;
		public IntPtr value;
	}

	[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
	public class Attribute
	{
		public uint type;
		public string key;
		public string value;
    
	}

	public class FireFox
	{
		private static int MAX_PROFILES = 5;			//FIXME:Maximum Profiles for Firefox - To be removed when done dynamically via a native api
		private static int LOAD_PROFILE_ALWAYSFROM_FILE = 1;		

#if WIN32
		private const string FF_LIB = "ad_ff.dll";
#else
		private const string FF_LIB = "libad_ff.so.1.1.1";
#endif



		//Initialization functions
		[DllImport(FF_LIB)]
		public static extern int FPM_GetProfileList(out IntPtr[] profileList, out IntPtr[] profileFlag);

		[DllImport(FF_LIB)]
		public static extern int FPM_FirefoxProfileInit(string profileName);

		[DllImport(FF_LIB)]
		public static extern int FPM_IsStoreAvailable();

		[DllImport(FF_LIB)]
		public static extern int FPM_FirefoxProfileExit(string profileName);

		//Master Password functions
		[DllImport(FF_LIB)]
		public static extern int FPM_IsMasterPasswordSet(string profileName);

		[DllImport(FF_LIB)]
		public static extern int FPM_CheckMasterPassword(string profileName, string masterPassword);

		//Signon functions
		[DllImport(FF_LIB)]
		public static extern int FPM_GetSignonData(string profileName,out IntPtr host,int doRefresh);

		[DllImport(FF_LIB)]
		public static extern int FPM_ModifyHost(string profileName, Host host, int doUpdate);

		[DllImport(FF_LIB)]
		public static extern int FPM_RemoveHost(string profileName, string hostName, int doUpdate);

		//TBD
		//int FPM_WriteSignonData(char *profileName)
		//int FPM_AddHost(char *profileName, struct Host *host, int doUpdate)
	
		public static int IsStoreAvailable()
		{
			return FPM_IsStoreAvailable();
		}

		public static int Remove_Host(string ProfileName, string hostName)
		{
			return (FPM_RemoveHost(ProfileName, hostName, 1)); 
		}

		public static int Modify_Host(string profileName, Host mhost, int doUpdate)
		{
			//Console.WriteLine("FireFox.cs : ProfileName : " + profileName);
			//Console.WriteLine("FireFox.cs : HostName : " + (String)Marshal.PtrToStringAnsi(mhost.hostName));
		
			return FPM_ModifyHost(profileName, mhost,1);
		}

		//--------------------------------------------------------------
		//GetDefaultProfileName
		//@param   None
		//@return  Default ProfileName on success
		//         else null if not retrivable 
		//--------------------------------------------------------------
		public static String GetDefaultProfileName()
		{

			IntPtr[] profileListIntPtr=new IntPtr[MAX_PROFILES];;
			IntPtr[] profileFlagsIntPtr=new IntPtr[MAX_PROFILES];;
			String[] profileList=null;   
			int[] profileFlags=null;  
			String profileName=null;   
			int profileFlag=0;  
			int profCount=0;
			String defaultProfileName=null;   

			//Console.WriteLine("FireFox:Invoking FPM_GetProfileList:");
			profCount=FPM_GetProfileList(out profileListIntPtr,out profileFlagsIntPtr);
			//Console.WriteLine("FireFox:No of Profiles found= "+profCount);
		
			//try
			///{
			for(int i=0; i< profCount; i++)
			{
				//Console.WriteLine("Firefox.cs : Inside The for Loop");
				profileName=Marshal.PtrToStringAnsi(profileListIntPtr[i]);
				profileFlag=(int)profileFlagsIntPtr[i];
				//Console.WriteLine("FireFox:Iter="+i+"profileName="+profileName);
				//Console.WriteLine("FireFox:Iter="+i+"profileFlag="+profileFlag);
				if(profileFlag==1)
					defaultProfileName=profileName;	//Get the default profile name to init later
			}

		
			return defaultProfileName;
		}


		//--------------------------------------------------------------
		//GetAllProfileNames
		//@param   None
		//@return  ProfileNames (String[]) - List of all Profile Names
		//	   else null 
		//--------------------------------------------------------------
		public static String[] GetAllProfileNames()
		{
			//TBD:To be implemented if\when required
			return null;
		}




		//--------------------------------------------------------------
		//GetProfileData
		//GetProfileData   for the specified profile
		//@param   
		//		profileName (string)
		//
		//@return  hostList (Host)   on success
		//         else null 
		//--------------------------------------------------------------
		public static Host GetProfileData(string profileName)
		{
			Host hostList;		// = new Host(); - NOT NEEDED SINCE WE GET THIS FILLED FROM NATIVE WHEN
			//			WE MARSHAL PTR TO STRUCTURE
			int methodStatusCode=-1;  
			String defaultProfileName = null;
			int initProfileStatus = -1;

			//if(methodStatusCode==1)
		{//If Init of the profile was sucessfull, get the sigon data to complete the aggregation
			IntPtr hostListIntPtr = new IntPtr();
			try
			{
				//Console.WriteLine("FireFox:Getting Data for profile "+profileName);
				methodStatusCode=-1;
				methodStatusCode = FPM_GetSignonData(profileName,out hostListIntPtr,LOAD_PROFILE_ALWAYSFROM_FILE);
				if( 1 != methodStatusCode )
				{
					//Console.WriteLine("FireFox:Getting Data for profile Failed with error "+methodStatusCode);
					hostList=null;
					return hostList;
				}  	
				hostList = null;
				hostList = (Host)Marshal.PtrToStructure(hostListIntPtr, typeof(Host));
				//This can be Null only when nothing is aggregated.
				if (((String)Marshal.PtrToStringAnsi(hostList.hostName)) == null ) 
				{
					//TBD: Log that there are no secrets to aggregate
					//Console.WriteLine("FireFox:no secrets to aggregate");
					hostList = null;
				}
			}
			catch(Exception e)
			{
				//Console.WriteLine("FireFox:Exception during invokation of FPM_GetSignonData");
				//Console.WriteLine(e.ToString());
				hostList = null;
			}

			//Uninitialize the profile
			//Console.WriteLine("FireFox:UnInitializing the Profile "+profileName);
			//UninitProfile(profileName);
		}
			return hostList;
		}

		//--------------------------------------------------------------
		//InitFFProfile
		//@param   profileName   name of the profile
		//@return  1     on success
		//         <=0   on error 
		//--------------------------------------------------------------
		public static int InitProfile(string profileName)
		{
			return FPM_FirefoxProfileInit(profileName);
		}


		//=================================================================

		//--------------------------------------------------------------
		//UninitProfile
		//UninitProfile   for the specified profile
		//@param   
		//		profileName (string)
		//
		//@return  	1     on success
		//		<=0   on error 
		//--------------------------------------------------------------
		public static int UninitProfile(string profileName)
		{
			int methodStatusCode=-1; 
 
			//Console.WriteLine("FireFox:UninitProfile for "+profileName);
			methodStatusCode=-1;
			methodStatusCode = FPM_FirefoxProfileExit(profileName);
			/*if( 1 != methodStatusCode )
		{
			Console.WriteLine("FireFox:UninitProfile Failed with error "+methodStatusCode);
		} */ 

			return methodStatusCode;					
		}


		//--------------------------------------------------------------
		//isMasterPasswordSetFor
		//Is MasterPassword Set For specified profile
		//@param   
		//		profileName (string)
		//
		//@param   profileName   name of the profile
		//	@return 1    if master password is set
		//        	0    if master password not set
		//--------------------------------------------------------------
		public static int isMasterPasswordSetFor(string profileName)
		{
			int methodStatusCode=0; 
 
			//Console.WriteLine("FireFox:isMasterPasswordSetFor "+profileName);
			methodStatusCode = FPM_IsMasterPasswordSet(profileName);

			return methodStatusCode;					
		}

		//--------------------------------------------------------------
		//checkMasterPassword
		//Check if the specified master password is correct or not. 
		//If it is correct then password is stored to the internal store for later use. 
		//If it is wrong then nothing is stored and 0 will be returned.
		//
		//@param   
		//	profileName (string)
		//	masterPassword (string)
		//
		//	@return  1   if the specified master password is correct
		//		 0   if the master password is wrong.
		//--------------------------------------------------------------
		public static int checkMasterPassword(string profileName,string masterPassword)
		{
			int methodStatusCode=0; 
 
			//Console.WriteLine("FireFox:checking MasterPassword for "+profileName);
			methodStatusCode = FPM_CheckMasterPassword(profileName,masterPassword);

			return methodStatusCode;					
		}

		//=================Local Methods====================================

	}
}