using System;
using System.Text;
using System.Collections;

using Novell.CASA.MiCasa.Common;

namespace sscs.cache
{
    public class KeyValue
    {
        private string m_key;
        public string Key
        {
            get
            {
                return m_key;
            }
            set
            {
                m_key = value;
            }
        }
        private byte[] m_value;

        public string GetValue()
        {
            return (DecryptValue());
        }

        public void SetValue(string sValue)
        {
            
			string oldValue = DecryptValue();
			
            if (oldValue.Equals(sValue))
                return;
            else
            {                    
				byte[] newEncryptedValue = EncryptValue(sValue);
                m_value = newEncryptedValue;
                m_modified = DateTime.Now;
            }
        }

        /*
        public string Value
        {
            get
            {
                // decrypt
                return (DecryptValue());
            }
            set
            {
                byte[] newEncrypteValue = EncryptValue(value);

                if ((newEncrypteValue != null) && (newEncrypteValue.Equals(m_value)))
                    return;
                else
                {                    
                    m_value = newEncrypteValue;
                    m_modified = DateTime.Now;
                }
            }
        }
        */


	private Hashtable mLinkedKeys = null; // = new Hashtable();

		public void AddLink(LinkedKeyInfo linkedInfo)
		{
			if (mLinkedKeys == null)
				mLinkedKeys = new Hashtable();

                        if(!mLinkedKeys.ContainsKey(linkedInfo.GetLinkID()))
  			    mLinkedKeys.Add(linkedInfo.GetLinkID(), linkedInfo);
		}

		public void RemoveLink(string sLinkID)
		{
			// remove link
			if (mLinkedKeys != null)
			{
				mLinkedKeys.Remove(sLinkID);
			}
		}

		public Hashtable GetLinkedKeys()
		{
			return mLinkedKeys;
		}


    private DateTime m_created;
    public DateTime CreatedTime
    {
        get
        {
            return m_created;
        }
    }

    private DateTime m_modified;
    public DateTime ModifiedTime
    {
        get
        {
            return m_modified;
        }
    }
        

        public KeyValue(string sKey, string sValue)
        {
            // NOTE: Order is important, do not change
            m_created = m_modified = DateTime.Now;
            m_key =  sKey;
            m_value = EncryptValue(sValue);                        
        }

        private byte[] EncryptValue(string sValue)
        {
            byte[] baValueClear = Encoding.Default.GetBytes(sValue);                        
            return (XORValue(baValueClear));
        }

        private string DecryptValue()
        {            
            byte[] baValueClear = XORValue(m_value);
            return Encoding.Default.GetString(baValueClear);                                    
        }

        private byte[] XORValue(byte[] baInput)
        {
            
            byte[] baOutput = new byte[baInput.Length];
            Random rand = new Random((int)m_created.Ticks);
            
            for (int i=0; i<baInput.Length; i++)
            {
                baOutput[i] = (byte)((int)baInput[i] ^ rand.Next());
            }        

            return baOutput;
        }

        public string ToXML()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("<ENTRY>");
            
            sb.Append("<KEY>");
            sb.Append(m_key);
            sb.Append("</KEY>");

            sb.Append("<VALUE>");
            sb.Append(m_value);
            sb.Append("</VALUE>");

            sb.Append("<MODIFIED>");
            sb.Append(m_modified.Ticks);
            sb.Append("</MODIFIED>");

            sb.Append("</ENTRY>");
            
            return sb.ToString();
        }
    }
}