// clsSettings.cs
// Copyright (C) 2008 Karel Jordaan karel_jordaan@yahoo.com.au
// 
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
// 
// This program 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 General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Windows.Forms;
using FileScope;
using GUIControlLogic.Error;
using ZANZIClient;

namespace GUIControlLogic.Persistence
{
    /// <summary>
    /// clsSettings read and write custom user GUI settings to XML file.
    /// </summary>
    ///<remarks>None</remarks>
    public class clsSettings : clsGlobalErr, IDisposable
    {
        #region Variable declaration

        /// <summary>
        /// Constant for the settings file name
        /// </summary>
        /// <remarks>Move to config file</remarks>
        private const string XML_FILE = "ZANZIUserSettings.cvc";

        /// <summary>
        /// A binary formatter
        /// </summary>
        /// <remarks>None</remarks>
        private readonly BinaryFormatter formatter = new BinaryFormatter();

        //private Hashtable  htbl = new Hashtable();

        /// <summary>
        /// A reference to the mdi parent
        /// </summary>
        /// <remarks>None</remarks>
        private clsMain m_clsMain;

        /// <summary>
        /// A referece to the options class
        /// </summary>
        /// <remarks>None</remarks>
        private frmOptions m_clsOptions;


        /// <summary>
        /// MDI frm location settings
        /// </summary>
        /// <remarks>None</remarks>
        private SerialMDIFormLocationSetting m_SerialMDIFormLocationSetting;

        /// <summary>
        /// the options settings object
        /// </summary>
        /// <remarks>None</remarks>
        internal SerialOptionsSetting m_SerialOptionsSetting;

        //private clsSerialSettings sscls =  new clsSerialSettings() ;

        #endregion

        #region Functions

        /// <summary>
        /// Reads the xml file into class variables
        /// </summary>
        /// <param name="cls">the mdiparent form pointer</param>
        /// <remarks>None</remarks>
        public clsSettings()
        {
            try
            {
//				//Deserialize the text file
                Stream stream = new FileStream(XML_FILE, FileMode.Open, FileAccess.Read, FileShare.None);
                clsSerialSettings sscls = (clsSerialSettings) formatter.Deserialize(stream);
                stream.Close();

                m_SerialOptionsSetting = sscls.SOP;
                m_SerialMDIFormLocationSetting = sscls.MDI;
            }

            catch (FileNotFoundException)
            {
                //Do nothing
                Debug.WriteLine("File not found");
            }
//			catch (VersionMismatchException  ex)
//			{
//				GUIControlLogic.Error. new GUIControlLogic.Error.clsExeption(ex);
//				//ErrByte = 1;
//			}
            catch (Exception  ex)
            {
                 new clsExeption(ex);
                //ErrByte = 1;
            }
        }

        /// <summary>	
        /// Function to load main form size and selection
        /// </summary>
        /// <param name="cls">reference to the mdi form</param>
        /// <remarks>None</remarks>
        public void LoadMDIFormLocationSettings(clsMain cls)
        {
            m_clsMain = cls;

            try
            {
//				Stream stream = new FileStream(XML_FILE, FileMode.Open, FileAccess.Read, FileShare.Read);
//				SerialMDIFormLocationSetting m_SerialMDIFormLocationSetting = (SerialMDIFormLocationSetting) formatter.Deserialize(stream);
//				stream.Close();

                m_clsMain.WindowState = (FormWindowState) m_SerialMDIFormLocationSetting.frmWinstate;

                if (m_clsMain.WindowState == FormWindowState.Normal)
                {
                    m_clsMain.Height = m_SerialMDIFormLocationSetting.frmHeight;
                    m_clsMain.Left = m_SerialMDIFormLocationSetting.frmLeft;
                    //m_cls.mnu =  ss.frmSound ;
                    m_clsMain.Top = m_SerialMDIFormLocationSetting.frmTop;
                    //m_cls.base . =  ss.frmTrvSelectedNode ;
                    //m_cls.Height =  ss.frmTrvWidth ;
                    m_clsMain.Width = m_SerialMDIFormLocationSetting.frmWidth;
                    //m_cls.WindowState = System.Windows.Forms.FormWindowState.Normal ;
                }
            }
            catch (NullReferenceException)
            {
                //Do nothing settings file not found
                Debug.WriteLine("File not found");
            }
            catch (Exception  ex)
            {
                 new clsExeption(ex);
                ErrByte = 1;
            }
        }


        /// <summary>
        /// Function to save main form size and selection
        /// </summary>
        /// <remarks>None</remarks>
        public void SaveMDIFormLocationSettings()
        {
            //SerialMDIFormLocationSetting ss = new SerialMDIFormLocationSetting();

            m_SerialMDIFormLocationSetting.frmHeight = m_clsMain.Height;
            m_SerialMDIFormLocationSetting.frmLeft = m_clsMain.Left;
            //ss.frmSound  = m_cls.Height;
            m_SerialMDIFormLocationSetting.frmTop = m_clsMain.Top;
            //ss.frmTrvSelectedNode  = m_cls.Height;
            //ss.frmTrvWidth = m_cls.Height;
            m_SerialMDIFormLocationSetting.frmWidth = m_clsMain.Width;
            m_SerialMDIFormLocationSetting.frmWinstate = m_clsMain.WindowState;

//			Stream stream = new FileStream(XML_FILE, FileMode.Create, FileAccess.Write, FileShare.None);
//			formatter.Serialize(stream, m_SerialMDIFormLocationSetting);
//			stream.Close();
        }

        /// <summary>
        /// Loads the saved options window values
        /// </summary>
        /// <param name="frm">a reference to the options form</param>
        /// <remarks>None</remarks>
        public void LoadOptionsSetting(frmOptions frm)
        {
            m_clsOptions = frm;

            try
            {
                m_clsOptions.ctrlUser.txtAlias.Text = m_SerialOptionsSetting.Alias;
                m_clsOptions.ctrlUser.txtCity.Text = m_SerialOptionsSetting.City;
                m_clsOptions.ctrlUser.txtCompany.Text = m_SerialOptionsSetting.Company;
                m_clsOptions.ctrlUser.txtFax.Text = m_SerialOptionsSetting.Fax;
                m_clsOptions.ctrlUser.txtName.Text = m_SerialOptionsSetting.Name;
                m_clsOptions.ctrlUser.txtOffice.Text = m_SerialOptionsSetting.Office;
                m_clsOptions.ctrlUser.txtPhone.Text = m_SerialOptionsSetting.Phone;
                m_clsOptions.ctrlUser.txtStreet.Text = m_SerialOptionsSetting.Street;
                m_clsOptions.ctrlUser.txtSuburb.Text = m_SerialOptionsSetting.Suburb;
                //m_clsOptions.ctrlUser.cboCountry.Text  = m_SerialOptionsSetting.cboCountry.Text ;

                m_clsOptions.ctrlInterface.chkSaveChats.Checked = m_SerialOptionsSetting.SaveChat;
                m_clsOptions.ctrlInterface.chkSaveResults.Checked = m_SerialOptionsSetting.SaveResult;
                m_clsOptions.ctrlInterface.chkSaveSearch.Checked = m_SerialOptionsSetting.SaveSearch;
                m_clsOptions.ctrlInterface.chkSaveSession.Checked = m_SerialOptionsSetting.SaveSession;
                m_clsOptions.ctrlInterface.chkStartUpdateCheck.Checked = m_SerialOptionsSetting.UpdateOnStartup;

                m_clsOptions.ctrlTransfer.udMaxUploads.Value = m_SerialOptionsSetting.maxUploads;
                m_clsOptions.ctrlTransfer.txtDownloadDir.Text = m_SerialOptionsSetting.dlDirectory;
                m_clsOptions.ctrlTransfer.txtTempDir.Text  = m_SerialOptionsSetting.tmpDirectory ;
                m_clsOptions.ctrlTransfer.chkAutoClearDownloads.Checked = m_SerialOptionsSetting.clearDl;
                m_clsOptions.ctrlTransfer.chkAutoClearUploads.Checked = m_SerialOptionsSetting.clearUp;
                m_clsOptions.ctrlNetwork.chkAutoConnect.Checked = m_SerialOptionsSetting.autoGnutella2;

                m_clsOptions.ctrlCnn.txtIncomingPort.Text = m_SerialOptionsSetting.port.ToString();

                if (m_SerialOptionsSetting.connectionType == EnumConnectionType.dialUp)
                    m_clsOptions.ctrlCnn.optDailup.Checked = true;

                if (m_SerialOptionsSetting.connectionType == EnumConnectionType.broadband)
                    m_clsOptions.ctrlCnn.optBroadBand.Checked = true;


                //	m_clsOptions.ctrlCnn.optDailup.Checked    = (int) m_SerialOptionsSetting.connectionType ;
                //	m_clsOptions.ctrlCnn.optBroadBand.Checked    != (bool) m_SerialOptionsSetting.connectionType;
                m_clsOptions.ctrlCnn.chkIncomingConnect.Checked = m_SerialOptionsSetting.firewall;

                m_clsOptions.ctrlChat.chkEnableChat.Checked = m_SerialOptionsSetting.allowChats;

                //	public volatile bool ultrapeerCapable;				//fulfilled gnutella ultrapeer requirements
                //	public volatile byte[] myGUID = new byte[16];		//permanent GUID for this computer
                //	public volatile int gConnectionsToKeep;				//gnutella connections to keep when ultrapeer
                //	public volatile bool updateNotify;					//notify user of new updates
                //	public volatile bool allowUltrapeer;				//allow ultrapeer
            }

            catch (Exception  ex)
            {
                 new clsExeption(ex);
                ErrByte = 1;
            }
        }

        /// <summary>
        /// save the options form values
        /// </summary>
        /// <remarks>None</remarks>
        public void SaveOptionsSetting()
        {
            try
            {
                m_SerialOptionsSetting.Alias = m_clsOptions.ctrlUser.txtAlias.Text;
                m_SerialOptionsSetting.City = m_clsOptions.ctrlUser.txtCity.Text;
                m_SerialOptionsSetting.Company = m_clsOptions.ctrlUser.txtCompany.Text;
                m_SerialOptionsSetting.Fax = m_clsOptions.ctrlUser.txtFax.Text;
                m_SerialOptionsSetting.Name = m_clsOptions.ctrlUser.txtName.Text;
                m_SerialOptionsSetting.Office = m_clsOptions.ctrlUser.txtOffice.Text;
                m_SerialOptionsSetting.Phone = m_clsOptions.ctrlUser.txtPhone.Text;
                m_SerialOptionsSetting.Street = m_clsOptions.ctrlUser.txtStreet.Text;
                m_SerialOptionsSetting.Suburb = m_clsOptions.ctrlUser.txtSuburb.Text;
                m_SerialOptionsSetting.Country = m_clsOptions.ctrlUser.cboCountry.Text;
                m_SerialOptionsSetting.SaveChat = m_clsOptions.ctrlInterface.chkSaveChats.Checked;
                m_SerialOptionsSetting.SaveResult = m_clsOptions.ctrlInterface.chkSaveResults.Checked;
                m_SerialOptionsSetting.SaveSearch = m_clsOptions.ctrlInterface.chkSaveSearch.Checked;
                m_SerialOptionsSetting.SaveSession = m_clsOptions.ctrlInterface.chkSaveSession.Checked;
                m_SerialOptionsSetting.UpdateOnStartup = m_clsOptions.ctrlInterface.chkStartUpdateCheck.Checked;

                m_SerialOptionsSetting.SaveChat = m_clsOptions.ctrlInterface.chkSaveChats.Checked;
                m_SerialOptionsSetting.SaveResult = m_clsOptions.ctrlInterface.chkSaveResults.Checked;
                m_SerialOptionsSetting.SaveSearch = m_clsOptions.ctrlInterface.chkSaveSearch.Checked;
                m_SerialOptionsSetting.SaveSession = m_clsOptions.ctrlInterface.chkSaveSession.Checked;
                m_SerialOptionsSetting.UpdateOnStartup = m_clsOptions.ctrlInterface.chkStartUpdateCheck.Checked;

                m_SerialOptionsSetting.maxUploads = (int) m_clsOptions.ctrlTransfer.udMaxUploads.Value;
                m_SerialOptionsSetting.dlDirectory = m_clsOptions.ctrlTransfer.txtDownloadDir.Text;
                m_SerialOptionsSetting.tmpDirectory = m_clsOptions.ctrlTransfer.txtTempDir.Text;
                m_SerialOptionsSetting.clearDl = m_clsOptions.ctrlTransfer.chkAutoClearDownloads.Checked;
                m_SerialOptionsSetting.clearUp = m_clsOptions.ctrlTransfer.chkAutoClearUploads.Checked;

                m_SerialOptionsSetting.autoGnutella2 = m_clsOptions.ctrlNetwork.chkAutoConnect.Checked;

                m_SerialOptionsSetting.port = Int32.Parse(m_clsOptions.ctrlCnn.txtIncomingPort.Text);
                //	m_SerialOptionsSetting.connectionType  = m_clsOptions.ctrlCnn.optDailup.Checked;
                //	m_SerialOptionsSetting.connectionType != m_clsOptions.ctrlCnn.optBroadBand.Checked    ;

                if (m_clsOptions.ctrlCnn.optDailup.Checked)
                    m_SerialOptionsSetting.connectionType = EnumConnectionType.dialUp;

                if (m_clsOptions.ctrlCnn.optBroadBand.Checked)
                    m_SerialOptionsSetting.connectionType = EnumConnectionType.broadband;


                m_SerialOptionsSetting.firewall = m_clsOptions.ctrlCnn.chkIncomingConnect.Checked;

                m_SerialOptionsSetting.allowChats = m_clsOptions.ctrlChat.chkEnableChat.Checked;

                //	public volatile bool ultrapeerCapable;				//fulfilled gnutella ultrapeer requirements
                //	public volatile byte[] myGUID = new byte[16];		//permanent GUID for this computer
                //	public volatile int gConnectionsToKeep;				//gnutella connections to keep when ultrapeer
                //	public volatile bool updateNotify;					//notify user of new updates
                //	public volatile bool allowUltrapeer;				//allow ultrapeer
            }

            catch (Exception  ex)
            {
                 new clsExeption(ex);
                ErrByte = 1;
            }
        }

        /// <summary>
        /// Loads filescope engen settings
        /// </summary>
        /// <remarks>None</remarks>
        public void LoadFileScopeSettings()
        {
            //Loads the settings into the p2p engen

            try
            {
                //FileScope.Stats.FileScopeSettings  thisSettings = new FileScope.Stats.FileScopeSettings();

                Stats.settings.allowChats = m_SerialOptionsSetting.allowChats;
                Stats.settings.allowUltrapeer = m_SerialOptionsSetting.allowUltrapeer;

                //zzoi 3june 2008 currently the settings are not set or saved in the options dlgbox
                //dev purposes hardcoded here
                Stats.settings.allowUltrapeer = true;


                Stats.settings.autoGnutella2 = m_SerialOptionsSetting.autoGnutella2;
                Stats.settings.clearDl = m_SerialOptionsSetting.clearDl;
                Stats.settings.clearUp = m_SerialOptionsSetting.clearUp;
                Stats.settings.connectionType = m_SerialOptionsSetting.connectionType;
                Stats.settings.dlDirectory = m_SerialOptionsSetting.dlDirectory;
                Stats.settings.firewall = m_SerialOptionsSetting.firewall;
                Stats.settings.gConnectionsToKeep = m_SerialOptionsSetting.gConnectionsToKeep;

                //zzoi 3june 2008 currently the settings are not set or saved in the options dlgbox
                //dev purposes hardcoded here
                Stats.settings.gConnectionsToKeep = 5;

                Stats.settings.ipAddress = m_SerialOptionsSetting.ipA;
                Stats.settings.maxUploads = m_SerialOptionsSetting.maxUploads;

                Stats.settings.myGUID = m_SerialOptionsSetting.myGUID;
                //zzoi 3june 2008 currently the settings are not set or saved in the options dlgbox
                //dev purposes hardcoded here
                Stats.settings.myGUID = GUID.newGUID();

                Stats.settings.port = m_SerialOptionsSetting.port;
                //FileScope.Stats.settings.transSplitPerc = m_SerialOptionsSetting.
                Stats.settings.ultrapeerCapable = m_SerialOptionsSetting.ultrapeerCapable;

                //zzoi 3june 2008 currently the settings are not set or saved in the options dlgbox
                //dev purposes hardcoded here
                Stats.settings.ultrapeerCapable = true;


                //thisSettings.updateNotify = 

                //Fill the engen settings variable with this one
                //if the class has bwwn init already 
                //else error will occur
                //FileScope.Stats.settings = thisSettings;
            }
            catch (Exception  ex)
            {
                 new clsExeption(ex);
                //	ErrByte = 1;
            }
        }

        /// <summary>
        /// Save filescope engen settings
        /// </summary>
        /// <remarks>None</remarks>
        public void SaveFileScopeSettings()
        {
            //some settings that the engen has changed and that needs persistance
            m_SerialOptionsSetting.ipA = Stats.settings.ipAddress;
        }

        #endregion

        #region Class to serialize

        /// <summary>
        /// the class to serialize to file
        /// takes all the settings for the application that needs saving
        /// </summary>
        /// <remarks>None</remarks>
        [Serializable]
        public class clsSerialSettings
        {
            /// <summary>
            /// Variable to hold the mdi location settings
            /// </summary>
            /// <remarks>None</remarks>
            public SerialMDIFormLocationSetting MDI;

            /// <summary>
            /// Variable to hold the options settings
            /// </summary>
            /// <remarks>None</remarks>
            public SerialOptionsSetting SOP;
        }

        #endregion

        #region Structures

        #region Nested type: SerialMDIFormLocationSetting

        /// <summary>
        /// struc for mdi form visual location settings
        /// </summary>
        /// <remarks>None</remarks>
        [Serializable]
        public struct SerialMDIFormLocationSetting
        {
            public int frmHeight;
            public int frmLeft;
            public int frmTop;
            public int frmWidth;
            public object frmWinstate;
        }

        #endregion

        #region Nested type: SerialOptionsSetting

        /// <summary>
        /// struct for settings for the options window
        /// </summary>
        /// <remarks>None</remarks>
        [Serializable]
        public struct SerialOptionsSetting
        {
            //frmOptionsUserInfo
            public string Alias;
            public volatile bool allowChats;
            public volatile bool allowUltrapeer; //allow ultrapeer
            public volatile bool autoGnutella2; //automatically connect to gnutella2 on startup
            public string City;
            public volatile bool clearDl; //clear completed downloads
            public volatile bool clearUp; //clear completed uploads
            public string Company;
            public volatile EnumConnectionType connectionType; //EnumConnectionType will take care of this
            public string Country;
            public volatile string dlDirectory; //download directory
            public volatile string tmpDirectory; //temp directory
            public string Fax;
            public volatile bool firewall; //are we behind a firewall?
            public volatile int gConnectionsToKeep; //gnutella connections to keep when ultrapeer
            public volatile string ipA; //public IP Address
            public volatile int maxUploads; //the maximum simultaneous uploads
            public volatile byte[] myGUID; //= new byte[16];		//permanent GUID for this computer
            public string Name;
            public string Office;
            public string Phone;
            public volatile int port; //port for incoming connections
            public bool SaveChat;
            public bool SaveResult;

            //frmOptionsSettings
            public bool SaveSearch;
            public bool SaveSession;
            public string Street;
            public string Suburb;
            public volatile bool ultrapeerCapable; //fulfilled gnutella ultrapeer requirements
            public volatile bool updateNotify; //notify user of new updates
            public bool UpdateOnStartup;
        }

        #endregion

        #endregion

        #region IDisposable Members

        /// <summary>
        /// serialize the variables to disk
        /// </summary>
        /// <remarks>None</remarks>
        public void Dispose()
        {
            //Serilize the values and text here

            clsSerialSettings temp = new clsSerialSettings();
            temp.MDI = m_SerialMDIFormLocationSetting;
            temp.SOP = m_SerialOptionsSetting;

            Stream stream = new FileStream(XML_FILE, FileMode.Create, FileAccess.Write, FileShare.None);
            formatter.Serialize(stream, temp);
            stream.Close();
        }

        #endregion
    }
}