using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using EnterpriseDesktop.Controls;
using System.Diagnostics;
using System.Deployment.Application;

namespace EnterpriseDesktop
{
    public partial class MainForm : Form
    {
        /// <summary>
        /// Holds all of the loaded controls.
        /// </summary>
        Hashtable _panel2Controls = new Hashtable();
        Hashtable _treeControls = new Hashtable();

        /// <summary>
        /// Shows how big the clickonce update is.
        /// </summary>
        long sizeOfUpdate = 0;

        public MainForm()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Displays controls in the main panel of the application.
        /// </summary>
        /// <param name="ctl"></param>
        public void ShowControlInPanel2(Control ctl)
        {
            if (_panel2Controls.Contains(ctl.Name))
            {
                Control validControl = _panel2Controls[ctl.Name] as Control;
                HideControlsInPanel2();
                validControl.Visible = true;
                return;
            }
            else
            {
                HideControlsInPanel2();
                _panel2Controls.Add(ctl.Name, ctl);
                ctl.Visible = true;
                splitContainer1.Panel2.Controls.Add(ctl);
            }
        }

        /// <summary>
        /// Hides the tree controls on the left nav.
        /// </summary>
        public void HideTreeControls()
        {
            foreach (Control ctl in splitContainer2.Panel1.Controls)
            {
                ctl.Visible = false;
            }
        }

        /// <summary>
        /// Displays a tree control for navigation in the left nav.
        /// </summary>
        /// <param name="ctl"></param>
        public void ShowTreeControl(Control ctl)
        {
            if (_treeControls.Contains(ctl.Name))
            {
                Control validControl = _treeControls[ctl.Name] as Control;
                HideTreeControls();
                validControl.Visible = true;
                return;
            }
            else
            {
                HideTreeControls();
                _treeControls.Add(ctl.Name, ctl);
                ctl.Visible = true;
                splitContainer2.Panel1.Controls.Add(ctl);
            }
        }

        /// <summary>
        /// Hides controls in the main panel.
        /// </summary>
        private void HideControlsInPanel2()
        {
            foreach (string key in _panel2Controls.Keys)
            {
                Control control = _panel2Controls[key] as Control;
                control.Visible = false;
            }
        }

        /// <summary>
        /// Displays the proper control in the main panel
        /// depending on what has been clicked.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
        {
            string name = e.Node.Name.ToString();
            switch (name)
            {
                case "home":
                    ShowControlInPanel2(new Home());
                    break;
                case "contacts":
                    ShowControlInPanel2(new EnterpriseDesktop.Contacts.WinForm.Contacts());
                    break;
            }
        }

        /// <summary>
        /// Load the Home Control in the main panel.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MainForm_Load(object sender, EventArgs e)
        {
            ShowControlInPanel2(new Home());
            ShowTreeControl(new HomeTree());

            // Get the latest version number and update the application
            // Get the version information
            if (System.Deployment.Application.ApplicationDeployment.IsNetworkDeployed)
            {
                System.Deployment.Application.ApplicationDeployment entDesktopApp = System.Deployment.Application.ApplicationDeployment.CurrentDeployment;
                this.Text += " - " + entDesktopApp.CurrentVersion;
            }
            else
            {
                checkForUpdatesToolStripMenuItem.Enabled = false;
            }
        }

        /// <summary>
        /// Updates the application every minute.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void _timerCheckForUpdate_Tick(object sender, EventArgs e)
        {
            UpdateApplication();
        }

        #region ClickOnce Deployment
        /// <summary>
        /// Uses ClickOnce to update the application is a new version
        /// is available.
        /// </summary>
        private void UpdateApplication()
        {
            if (ApplicationDeployment.IsNetworkDeployed)
            {
                ApplicationDeployment ad = ApplicationDeployment.CurrentDeployment;
                ad.CheckForUpdateCompleted += new CheckForUpdateCompletedEventHandler(ad_CheckForUpdateCompleted);
                ad.CheckForUpdateProgressChanged += new DeploymentProgressChangedEventHandler(ad_CheckForUpdateProgressChanged);

                ad.CheckForUpdateAsync();
                // Stop the timer in case the user clicks the check for update button
                // or because the update is taking longer than what the timer is set
                _timerCheckForUpdate.Stop();
            }
        }

        void ad_CheckForUpdateProgressChanged(object sender, DeploymentProgressChangedEventArgs e)
        {
            downloadStatus.Text = String.Format("Downloading: {0}. {1:D}K of {2:D}K downloaded.", GetProgressString(e.State), e.BytesCompleted / 1024, e.BytesTotal / 1024);
        }

        string GetProgressString(DeploymentProgressState state)
        {
            if (state == DeploymentProgressState.DownloadingApplicationFiles)
            {
                return "application files";
            }
            else if (state == DeploymentProgressState.DownloadingApplicationInformation)
            {
                return "application manifest";
            }
            else
            {
                return "deployment manifest";
            }
        }

        void ad_CheckForUpdateCompleted(object sender, CheckForUpdateCompletedEventArgs e)
        {
            ApplicationDeployment ad = ApplicationDeployment.CurrentDeployment;
            ad.CheckForUpdateCompleted -= new CheckForUpdateCompletedEventHandler(ad_CheckForUpdateCompleted);
            if (e.Error != null)
            {
                MessageBox.Show("ERROR: Could not retrieve new version of the application. Reason: \n" + e.Error.Message + "\nPlease report this error to the system administrator.");
                _timerCheckForUpdate.Start();
                return;
            }
            else if (e.Cancelled == true)
            {
                MessageBox.Show("The update was cancelled.");
                _timerCheckForUpdate.Start();
                return;
            }

            // Ask the user if they would like to update the application now.
            if (e.UpdateAvailable)
            {
                sizeOfUpdate = e.UpdateSizeBytes / 1024;

                if (!e.IsUpdateRequired)
                {
                    DialogResult dr = MessageBox.Show("A new version of Enterprise Desktop is available!  Before updating you should save your current work.\nWould you like to update Enterprise Desktop to the new version?\n\nDownload Size: " + sizeOfUpdate + "K", "Update Available", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                    if (DialogResult.Yes == dr)
                    {
                        BeginUpdate();
                    }
                    else
                    {
                        _timerCheckForUpdate.Start();
                    }
                }
                else
                {
                    MessageBox.Show("A mandatory update is available for your Enterprise Desktop.\n\nPlease save your work and proceed with the update.\nAfter the update is completed the application will restart.");
                    BeginUpdate();
                }
            }
            else if (_showUpdateMessage)
            {
                MessageBox.Show("No update found.", "Enterprise Desktop Update", MessageBoxButtons.OK, MessageBoxIcon.Information);
                _timerCheckForUpdate.Start();
                _showUpdateMessage = false; // don't show it again unless user clicks on the check update.
            }
            else
            {
                // Set text on bottom to blank
                downloadStatus.Text = "";
                _timerCheckForUpdate.Start();
            }
        }

        /// <summary>
        /// Starts the asynchronous update of the application.
        /// </summary>
        private void BeginUpdate()
        {
            ApplicationDeployment ad = ApplicationDeployment.CurrentDeployment;
            ad.UpdateCompleted += new AsyncCompletedEventHandler(ad_UpdateCompleted);
            // Indicate progress in the application's status bar.
            ad.UpdateProgressChanged += new DeploymentProgressChangedEventHandler(ad_UpdateProgressChanged);
            ad.UpdateAsync();
        }

        void ad_UpdateProgressChanged(object sender, DeploymentProgressChangedEventArgs e)
        {
            String progressText = String.Format("{0:D}K out of {1:D}K downloaded - {2:D}% complete", e.BytesCompleted / 1024, e.BytesTotal / 1024, e.ProgressPercentage);
            downloadStatus.Text = progressText;
        }

        void ad_UpdateCompleted(object sender, AsyncCompletedEventArgs e)
        {
            ApplicationDeployment ad = ApplicationDeployment.CurrentDeployment;
            ad.UpdateCompleted -= new AsyncCompletedEventHandler(ad_UpdateCompleted);
            if (e.Cancelled)
            {
                MessageBox.Show("The update of the application's latest version was cancelled.");
                _timerCheckForUpdate.Start();
                return;
            }
            else if (e.Error != null)
            {
                MessageBox.Show("ERROR: Could not install the latest version of Enterprise Desktop. Reason: \n" + e.Error.Message + "\nPlease report this error to the system administrator.");
                _timerCheckForUpdate.Start();
                return;
            }

            DialogResult dr = MessageBox.Show("The application has been updated.\nThe application must be restarted in order for changes to take effect.\n\nWould you like to restart the application now?", "Restart Application", MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
            if (DialogResult.OK == dr)
            {
                Application.Restart();
            }
        }

        bool _showUpdateMessage = false;
        private void checkForUpdatesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            _showUpdateMessage = true;
            UpdateApplication();
        }

        private void checkForUpdatesToolStripMenuItem_Click_1(object sender, EventArgs e)
        {
            UpdateApplication();
        }
        #endregion

        private void contentsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            EnterpriseDesktop.Common.WinForm.Help help = new EnterpriseDesktop.Common.WinForm.Help(new Uri("http://localhost:2969/Documentation/default.aspx"));
            help.Show();
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }
    }
}