/***********************************************************************
 * 
 *  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.Collections;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
using System.Text;

namespace Novell.CASA.CASAPolicy
{
public class ICASAPol
{
    static string GetPolicyFilePath()
    {
        try 
        {
            /* There needs to be a better way to get the HOME dir,
             * if this is used by miCASAd(as it runs as root).
             */

            int platform = (int)Environment.OSVersion.Platform;
            string homeDir;

            if ( (platform == 128) || ( platform == 4) )
            {
                homeDir = System.Environment.GetEnvironmentVariable("HOME");
            }
            else
            {
                 homeDir =  (System.Environment.GetEnvironmentVariable("USERPROFILE"));
            }

            string path = homeDir + XmlConsts.policyFileName;
            return path;
        }
        catch(Exception e)
        {
            //Console.WriteLine(e.ToString());
        }
        return "";
    }


    static public CASAPol[] GetPolicies()
    {
        try
        {
            if(!File.Exists(GetPolicyFilePath()))
                return null;
            CASAPol[] policies = new CASAPol[4];
            policies[0] = GetPolicy(CASAPolType.AGGREGATION_POL);
            policies[1] = GetPolicy(CASAPolType.PERSISTENCE_POL);
            policies[2] = GetPolicy(CASAPolType.UI_POL);
            policies[3] = GetPolicy(CASAPolType.SYNCH_POL);
            return policies;
        }
        catch(Exception e)
        {
            //Console.WriteLine(e.ToString());
        }
        return null;
    }

    static public bool SetPolicies(CASAPol[] polList)
    {
        try
        {
            XmlDocument doc = new XmlDocument();
            
            XmlElement rootElem = doc.CreateElement(XmlConsts.CASAPolicyNode);
            doc.AppendChild(rootElem);
            for(int i = 0; i < polList.Length; i++)
            {
                if(polList[i] != null)
                    polList[i].AppendToDoc(doc);
            }
/*
            FileStream fs = new FileStream(GetPolicyFilePath(),FileMode.Create);
            XmlTextWriter writer = new XmlTextWriter(fs,null);
            writer.Formatting = Formatting.Indented;
            doc.Save(writer);
            fs.Close();
            writer.Close();
*/
            XmlTextWriter writer = new XmlTextWriter(GetPolicyFilePath(),null);
            writer.Formatting = Formatting.Indented;
            doc.Save(writer);
            writer.Close();
            return true;
        }
        catch(Exception e)
        {
            //Console.WriteLine(e.ToString());
        }
        return false;
    }
    static private AggregationPol GetAggPol(XmlDocument doc)
    {
        string xpath = "";
        try
        {
            xpath = "//" + XmlConsts.AggregationPolicyNode;
            XmlNode aggNode = doc.SelectSingleNode(xpath);
            Store store = null;
            ArrayList storeList = new ArrayList();
            if( null != aggNode )
            {
                XmlNodeList storeNodeList = aggNode.SelectNodes("descendant::Store");
                foreach( XmlNode node in storeNodeList )
                {
                    XmlAttributeCollection attrList = node.Attributes;    
                    string storeName = (attrList[XmlConsts.StoreNameAttr]).Value;

                    attrList = node.Attributes;    
                    string storeId = (attrList[XmlConsts.StoreIdAttr]).Value;
                    store = new Store(storeName, storeId);
                
                    storeList.Add(store);
                }    
                AggregationPol aggPol = new AggregationPol(storeList);
                return aggPol;             
            }
        }
        catch(Exception e)
        {
            //Console.WriteLine(e.ToString());
        }

        return null;
    }
    static private PersistencePol GetPersistencePol(XmlDocument doc)
    {
        string xpath = "";
        try
        {
            xpath = "//" + XmlConsts.PersistencePolicyNode;
            XmlNode persistenceNode = doc.SelectSingleNode(xpath);
            if( null != persistenceNode )
            {
                xpath = "//" + XmlConsts.StoreFileLocationAttr;
                XmlNode storeFileLocationNode = persistenceNode.SelectSingleNode(xpath);
                string storeFileLocation = storeFileLocationNode.InnerText;

                XmlAttributeCollection attrColl = storeFileLocationNode.Attributes;
                string os = (attrColl[XmlConsts.OSAttr]).Value;

                xpath = "//" + XmlConsts.PollIntervalNode;
                XmlNode pollIntervalNode = persistenceNode.SelectSingleNode(xpath);
                int pollInterval = Convert.ToInt32(pollIntervalNode.InnerText);

                PersistencePol persistencePol = new PersistencePol(os,storeFileLocation, pollInterval);
                return persistencePol;
            }
        }
        catch(Exception e)
        {
            //Console.WriteLine(e.ToString());
        }
        return null;
    }
    static private UIPol GetUIPol(XmlDocument doc)
    {
        string xpath = "";
        try
        {
            xpath = "//" + XmlConsts.UIPolicyNode;
            XmlNode uiNode = doc.SelectSingleNode(xpath);
            if( null != uiNode )
            {
                XmlAttributeCollection attrColl = uiNode.Attributes;
                bool showInTaskBar = Convert.ToBoolean((attrColl[XmlConsts.ShowInTaskBarAttr]).Value);
                bool showSecretValue = Convert.ToBoolean((attrColl[XmlConsts.ShowSecretValueAttr]).Value);
                bool showSecretInClearText = Convert.ToBoolean((attrColl[XmlConsts.ShowSecretInClearTextAttr]).Value);

                xpath = "//" + XmlConsts.SynchEngineStartModeNode;
 
                XmlNode modeNode = uiNode.SelectSingleNode(xpath);
                string mode = modeNode.InnerText;
 
                UIPol uiPol = new UIPol(showInTaskBar, showSecretValue, showSecretInClearText, mode);
                return uiPol;
            }
        }
        catch(Exception e)
        {
            //Console.WriteLine(e.ToString());
        }
        return null;
    }

    static private SynchPol GetSynchPol(XmlDocument doc)
    {
        SynchPol synchPol = null;
        ArrayList linkGrpList = new ArrayList();
        ArrayList linksList   = new ArrayList();
        ArrayList linkKeyList;// = new ArrayList();
        LinkKey linkKey = null;
        Link link = null;
        LinkGroup linkGrp = null;
        try
        {
            XmlNode synchNode = doc.SelectSingleNode("//SynchPolicy");
            if( null != synchNode )
            {
                XmlNodeList grpNodeList = synchNode.SelectNodes("descendant::LinkGroup");
                foreach( XmlNode node in grpNodeList )
                {
                    XmlNodeList linkNodeList = node.SelectNodes("descendant::Link");
                    foreach( XmlNode linkNode in linkNodeList )
                    {
                        XmlNodeList linkKeyNodeList = linkNode.SelectNodes("descendant::LinkKey");
                        linkKeyList = new ArrayList();
                        foreach( XmlNode linkKeyNode in linkKeyNodeList )
                        {
                            linkKey = GetLinkKey(linkKeyNode);
                            linkKeyList.Add(linkKey);
                        }
                        link = new Link(linkKeyList);
                        linksList.Add(link);
                    }//end of linkNodeList loop
                    linkGrp = new LinkGroup(linksList);
                    linkGrpList.Add(linkGrp);
                }//end of grpNodeList loop
            synchPol = new SynchPol(linkGrpList);
            }
        }
        catch(Exception e)
        {
            //Console.WriteLine(e.ToString());
        }
        return synchPol;
    }

    static private LinkKey GetLinkKey(XmlNode keyNode)
    {
        LinkKey linkKey = null;
        try
        {
            XmlAttributeCollection attrList = keyNode.Attributes;

            string storeName = (attrList[XmlConsts.StoreNameAttr]).Value;
            string storeId = (attrList[XmlConsts.StoreIdAttr]).Value;
            string secretId = (attrList[XmlConsts.SecretIdAttr]).Value;
            string keyId = (attrList[XmlConsts.KeyAttr]).Value;
            string folderId;
            if(storeName == XmlConsts.KwalletStoreName)
            {
                folderId = (attrList[XmlConsts.FolderIdAttr]).Value;
                linkKey = new KWLinkKey(storeId,folderId,secretId,keyId);	
            }
            else if(storeName == XmlConsts.GnomeKeyringStoreName)
            {
                linkKey = new GKLinkKey(storeId,secretId,keyId);
            }
            else if(storeName == XmlConsts.MozillaStoreName)
            {
                linkKey = new MZLinkKey(storeId,secretId,keyId);
            }
            else if(storeName == XmlConsts.FirefoxStoreName)
            {
                linkKey = new FXLinkKey(storeId,secretId,keyId);
            }
            else if(storeName == XmlConsts.MicasaStoreName)
            {
                linkKey = new CASALinkKey(secretId,keyId);
            }
            
            
        }
        catch(Exception e)
        { 
            //Console.WriteLine(e.ToString());
        }
        return linkKey;
    }

    static public CASAPol GetPolicy(CASAPolType policyType)
    {
        CASAPol pol = null;
        try
        {
            XmlDocument doc = new XmlDocument();
            if(!File.Exists(GetPolicyFilePath()))
                return null;
            doc.Load(GetPolicyFilePath());
            switch(policyType)
            {
                case CASAPolType.AGGREGATION_POL:
                {
                    pol = GetAggPol(doc);
                    break;
                }
                case CASAPolType.PERSISTENCE_POL:
                {
                    pol = GetPersistencePol(doc);
                    break;
                }
                case CASAPolType.UI_POL:
                {
                    pol = GetUIPol(doc);
                    break;
                }
                case CASAPolType.SYNCH_POL:
                {
                    pol = GetSynchPol(doc);
                    break;
                }
            }   
        }
        catch(Exception e)
        {
            //Console.WriteLine(e.ToString());
        }
        return pol;
    }
    static public bool SetPolicy(CASAPol policy)
    {
        try
        {
            XmlDocument doc = new XmlDocument();
            if(File.Exists(GetPolicyFilePath()))
                doc.Load(GetPolicyFilePath());
            CASAPolType policyType = policy.PolicyType;

            AggregationPol aggPol = null;
            PersistencePol persistencePol = null;
            UIPol uiPol = null;
            SynchPol synchPol = null;

            switch(policyType)
            {
                case CASAPolType.AGGREGATION_POL:
                {
                    persistencePol = GetPersistencePol(doc);
                    uiPol = GetUIPol(doc);
                    synchPol = GetSynchPol(doc);
                    aggPol = (AggregationPol)policy;
                    break;
                }
                case CASAPolType.PERSISTENCE_POL:
                {
                    aggPol = GetAggPol(doc);
                    uiPol = GetUIPol(doc);
                    synchPol = GetSynchPol(doc);
                    persistencePol = (PersistencePol)policy;
                    break;
                } 
                case CASAPolType.UI_POL:
                {
                    aggPol = GetAggPol(doc);
                    persistencePol = GetPersistencePol(doc);
                    synchPol = GetSynchPol(doc);
                    uiPol = (UIPol)policy;
                    break;
                }
                case CASAPolType.SYNCH_POL:
                {
                    aggPol = GetAggPol(doc);
                    persistencePol = GetPersistencePol(doc);
                    uiPol = GetUIPol(doc);
                    synchPol = (SynchPol)policy;
                    break;
                }
           }
           CASAPol[] policies = new CASAPol[4];
           policies[0] = aggPol;
           policies[1] = persistencePol;
           policies[2] = uiPol;
           policies[3] = synchPol;
           SetPolicies(policies);
           return true;
       }
       catch(Exception e)
       {
           //Console.WriteLine(e.ToString());
       } 
       return false;
    }

   /* Should we support this? TBD later if required.
    */
    static public bool RemovePolicy(CASAPolType policyType, CASAPol policy)
    {

        return true;
    }
}
}