using System;
using System.Runtime.InteropServices;
using System.Collections;
using System.Threading;
using Gtk;
using GLib;

namespace Novell.CASA.DataEngines.GK
{
    [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;
    }

    public class Attribute
    {
        public uint type;
        public string key;
        public string value;
    
    }

    public class GnomeKeyring
    {
        [DllImport("libad_gk.so")]
        public static extern int GetKeyrings(out IntPtr list);
        [DllImport("libad_gk.so")]
        public static extern int GetKeyringInfo(string name,KeyringInfo info);
        [DllImport("libad_gk.so")]
        public static extern int GetItems(string keyring,out IntPtr list);
        [DllImport("libad_gk.so")]
        public static extern int GetItemInfo(string keyring,int itemId, NativeItemInfo info);
        [DllImport("libad_gk.so")]
        public static extern int GetAttributeList(string keyring,int itemId, out IntPtr attrList);
        [DllImport("libad_gk.so")]
        public static extern int FreeAttributeList(IntPtr attrList);

        public static KeyringInfo GKGetKeyringInfo(string name)
        {
            KeyringInfo info = null;
            try
            {
                info = new KeyringInfo();
                int retVal = GetKeyringInfo(name,info);
                if( 0 != retVal )
                    info = null;
            }
            catch(Exception e)
            {
                Console.WriteLine(e.ToString());
                info = null;
            }
            return info;
        }

        public static void PrintKeyringInfo(KeyringInfo info)
        {
            if( null == info )
                return;
            try
            {
                Console.WriteLine("lockOnIdle = " + info.lockOnIdle);
                Console.WriteLine("lockTimeout = " + info.lockTimeout);
                Console.WriteLine("mTime = " + info.mTime);
                Console.WriteLine("cTime = " + info.cTime);
                Console.WriteLine("isLocked = " + info.isLocked);
            }
            catch(Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
    
        public static ItemInfo GKGetItemInfo(string keyring, int itemId)
        {
            ItemInfo info = null;
            try
            {
                NativeItemInfo nativeItemInfo = new NativeItemInfo();
                int retVal = GetItemInfo(keyring, itemId, nativeItemInfo);

                if( 0 != retVal )
                    info = null;
                else
                {
                    info = new ItemInfo();
                    if(nativeItemInfo.itemType == 0)
                        info.itemType = "Generic Secret";
                    else if(nativeItemInfo.itemType == 1)
                        info.itemType = "Network Password";
                    else if(nativeItemInfo.itemType == 2)
                        info.itemType = "Note";
                    else
                        info.itemType = "No Type"; // need to have a better name
                    
                    info.displayName = Marshal.PtrToStringAnsi(nativeItemInfo.displayName);
                    info.secret = Marshal.PtrToStringAnsi(nativeItemInfo.secret);
                    info.mTime = nativeItemInfo.mTime;
                    info.cTime = nativeItemInfo.cTime;
                }
            }
            catch(Exception e)
            {
                Console.WriteLine(e.ToString());
                info = null;
            }
            return info;
        }

        public static void PrintItemInfo(ItemInfo info)
        {
            if( null == info )
                return;
            try
            {
                Console.WriteLine("CS : itemType = " + info.itemType);
                Console.WriteLine("CS : displayName = " + info.displayName);
                Console.WriteLine("CS : secret = " + info.secret);
                Console.WriteLine("CS : mTime = " + info.mTime);
                Console.WriteLine("CS : cTime = " + info.cTime);
            }
            catch(Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        public static ArrayList GKGetKeyrings()
        {
            ArrayList retList;
            try
            {
                retList = new ArrayList();
                IntPtr list = new IntPtr();
                int retVal = GetKeyrings(out list);
                if ( 0 != retVal )
                    retList = null;
                GLib.List keyringList = new List(list,typeof(string));
                IEnumerator etor = (IEnumerator)(keyringList.GetEnumerator());
                string name;
                while(etor.MoveNext())
                {
                    name = (string)etor.Current;
                    retList.Add(name);
                }
            }
            catch(Exception e)
            {
                Console.WriteLine(e.ToString());
                retList = null;
            }
            return retList;
        }

        public static ArrayList GKGetItems(string keyring)
        {
            ArrayList retList = null;
            try
            {
                retList = new ArrayList();
                IntPtr list = new IntPtr();
                int retVal = GetItems(keyring,out list);
                if( 0 != retVal )
                    retList = null;
                GLib.List itemList = new List(list,typeof(int));
                IEnumerator etor = (IEnumerator)(itemList.GetEnumerator());
                int itemId;
                while(etor.MoveNext())
                {
                    itemId = (int)etor.Current;
                    retList.Add(itemId);
                }
            }
            catch(Exception e)
            {
                Console.WriteLine(e.ToString());
                retList = null;
            }
            return retList;
        }

        public static ArrayList GKGetAttributeList(string keyring, int itemId)
        {
            ArrayList retList = null;
            try
            {
                retList = new ArrayList();
                IntPtr list = new IntPtr();
                int retVal = GetAttributeList(keyring, itemId,out list);
                if( 0 != retVal )
                    retList = null;
                GLib.List attrList = new List(list,typeof(int));
                IEnumerator etor = (IEnumerator)(attrList.GetEnumerator());
                while(etor.MoveNext())
                {
                    int test = (int)etor.Current;
                    IntPtr ptr = new IntPtr(test);
   
                    NativeAttribute attr = new NativeAttribute();
                    attr = (NativeAttribute)Marshal.PtrToStructure(ptr,typeof(NativeAttribute));
  
                    string key = Marshal.PtrToStringAnsi(attr.key);
                    string value = Marshal.PtrToStringAnsi(attr.value);

                    Attribute retAttr = new Attribute();
                    retAttr.type = attr.type;
                    retAttr.key = String.Copy(key);
                    retAttr.value = String.Copy(value);
                    retList.Add(retAttr);
                }
                if(retList.Count > 0)
                    FreeAttributeList(list);
            }
            catch(Exception e)
            {
                Console.WriteLine(e.ToString());
                retList = null;
            }
            return retList;
        }

        public static void PrintAttrList(ArrayList attrList)
        {
            if( null == attrList )
                return;
            Attribute attr;
            try
            {
                IEnumerator etor = (IEnumerator)(attrList.GetEnumerator());
                while(etor.MoveNext())
                {
                    attr = (Attribute)(etor.Current);
                    Console.WriteLine("CS : AttrType = " + attr.type);
                    Console.WriteLine("CS : AttrKey = " + attr.key);
                    Console.WriteLine("CS : AttrValue = " + attr.value);
                }
            }    
            catch(Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }
    }
}