using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using GlobalScope;



namespace UpdateVS
{
    public partial class Updater : Form
    {
        private List<String> _Messages = new List<string>();
        private Boolean LegalUpdate = true;
        public String FileNameExceptionContent
        {
            get
            {
                // Returns part of exec name to scan for and ignore in deleting and copying
                System.Reflection.Assembly ass = System.Reflection.Assembly.GetEntryAssembly();
                string exe = System.IO.Path.GetFullPath(ass.Location);
                string name = new FileInfo(exe).Name;
                string ext = new FileInfo(exe).Extension;
                name = name.Replace( ext, "");
                return name.ToLower();
            }
        }
        private String _FileFromCommandLine = "";

        public Updater(string[] args)
        {
            InitializeComponent();

            if (args.Length != 2)
                LegalUpdate = false;
            else
            {
                if (!args[1].StartsWith(Globals.LegalUpdateKeyWord))
                {
                    LegalUpdate = false;
                }

                else
                {
                    _FileFromCommandLine = Globals.SpaceIn(args[1].Substring(Globals.LegalUpdateKeyWord.Length));
                    LegalUpdate = true;
                }

            }

            // Build version
            System.Reflection.Assembly ass = System.Reflection.Assembly.GetEntryAssembly();
            string exe = System.IO.Path.GetFullPath(ass.Location);
            DateTime d = new System.IO.FileInfo(exe).LastWriteTimeUtc;
            this.Text = String.Format(Globals.UpdaterModuleDescription + " (v{0:0000}{1:00}{2:00})", d.Year, d.Month, d.Day);
        }

        private void Updater_Load(object sender, EventArgs e)
        {
            this.Text = Globals.UpdaterModuleDescription;


            // Center screen
            this.Location = new Point((int)Math.Round((Screen.PrimaryScreen.Bounds.Width - this.Size.Width) / 2.0), (int)Math.Round((Screen.PrimaryScreen.Bounds.Height - this.Size.Height) / 2.0));

            

            lbox.Items.Clear();

            System.Reflection.Assembly ass = System.Reflection.Assembly.GetEntryAssembly();
            string exe = System.IO.Path.GetFullPath(ass.Location);
            if (exe.ToLower().Contains("silicium"))
            {
                MessageBox.Show("You can only run '" + Globals.UpdaterModuleDescription + "' locally!", Globals.UpdaterModuleDescription, MessageBoxButtons.OK, MessageBoxIcon.Error);
                Application.Exit();
            }
            _Messages.Add("Updating...");
            _Messages.Add("");
            _Messages.Add("Server copy is on " + Globals.PathToServerVersion);
            _Messages.Add("");

            UpdateMessages();

            startupTimer.Start();
        }

        private void startupTimer_Tick(object sender, EventArgs e)
        {
            // Prevent from occuring again
            startupTimer.Stop();

            // Check if the update is started legally
            if (!LegalUpdate)
            {
                _Messages.Clear();
                _Messages.Add(Globals.UpdaterModuleDescription + " was not called by " + Globals.SoftwareDescription + "!");
                UpdateMessages();
                return;
            }
            

            // Add commandline argument to messageboard
            if (_FileFromCommandLine.Length > 2)
                _Messages.Add("Command line argument: " + _FileFromCommandLine);



            // Get local directory
            string LocalDir = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location) + "\\";


            // Make fileLists
            string[] localFileList = Directory.GetFiles(LocalDir);
            
            _Messages.Add(String.Format("{0} files found in local folder", localFileList.Length));
            UpdateMessages();

            string[] serverFileList;
            if (Directory.Exists(Globals.PathToServerVersion))
            {
                serverFileList = Directory.GetFiles(Globals.PathToServerVersion);

                _Messages.Add(String.Format("{0} files found on server", localFileList.Length));
                UpdateMessages();
            }
            else
            {
                _Messages.Add("Serverpath not accessible!");
                UpdateMessages();
                return;
            }


            Boolean ErrorEncountered = false;


            #region Deleting old files

            List<string> serverFileNames = new List<string>();
            foreach (string s in serverFileList)
                serverFileNames.Add(new FileInfo(s).Name);

            // Delete old files
            foreach (string f in localFileList)
            {

                


                if (f.ToLower().IndexOf(FileNameExceptionContent) < 0)
                {
                    FileInfo fInfo = new FileInfo(f);
                    if (serverFileNames.Contains(fInfo.Name))
                    {
                        // Do nothing
                    }
                    else
                    {
                        try
                        {
                            _Messages.Add(String.Format("Removing : {0}\n", f));
                            UpdateMessages();
                            fInfo.Delete();
                        }
                        catch(Exception ex)
                        {
                            _Messages.Add(String.Format("Failed to remove : {0}", f));
                            _Messages.Add(String.Format("    [{0}]", ex.Message));
                            UpdateMessages();
                        }
                    }
                }

            }
            #endregion Deleting old files



            #region Copy to local
            foreach (string serverFilePath in serverFileList)
            {
                if (serverFilePath.ToLower().IndexOf(FileNameExceptionContent) < 0)
                {
                    string targetFilePath = "";


                    try
                    {
                        string name = new FileInfo(serverFilePath).Name;
                        
                        targetFilePath = LocalDir + name;

                        // Only copy if newer or does not exist
                        if (File.Exists(targetFilePath))
                        {
                            FileInfo target = new FileInfo(targetFilePath);
                            FileInfo source = new FileInfo(serverFilePath);

                            if (source.LastWriteTimeUtc > target.LastWriteTimeUtc)
                            {
                                File.Copy(serverFilePath, targetFilePath, true);
                                _Messages.Add(String.Format("Updating : {0}\n", targetFilePath));
                            }
                        }
                        else
                        {
                            File.Copy(serverFilePath, targetFilePath, true);
                            _Messages.Add(String.Format("Copying : {0}\n", targetFilePath));
                        }
                    }
                    catch(Exception ex)
                    {
                        ErrorEncountered = true;
                        _Messages.Add(String.Format("Failed to copy : {0}", targetFilePath));
                        _Messages.Add(String.Format("    [{0}]", ex.Message));
                    }
                    UpdateMessages();
                }
            }
            #endregion Copy to local


            Globals.RegisterUser(Globals.UpdaterModuleDescription + " (v" + Globals.BuildVersion + ")");

            _Messages.Add("User register updated");
            UpdateMessages();


            try
            {
                if (!ErrorEncountered)
                {
                    String argument = Globals.CalledByUpdaterKeyWord + Globals.SpaceOut(_FileFromCommandLine);
                    System.Diagnostics.Process.Start(LocalDir + Globals.FileNameOfSoftware, argument);
                }
            }
            catch (Exception ex)
            {
                ErrorEncountered = true;
                _Messages.Add(String.Format("Failed to launch {0}", Globals.FileNameOfSoftware));
                _Messages.Add(String.Format("    [{0}]", ex.Message));
            }
            finally
            {
                if(!ErrorEncountered)
                    Application.Exit();
            }
        }

        private void UpdateMessages()
        {
            int stop = _Messages.Count - 1;
            int start = (int)Math.Max(stop - 19, 0);

            lbox.Items.Clear();

            for (int i = start; i <= stop; i++)
                lbox.Items.Add(_Messages[i]);

            lbox.Refresh();
            lbox.ClearSelected();
            this.Refresh();
            System.Threading.Thread.Sleep(50);
        }

    }
}
