using System;
using System.IO;
using System.Windows;
using System.Threading;
using System.Diagnostics;
using System.Windows.Media;
using System.Windows.Input;
using System.ComponentModel;
using System.Windows.Controls;
using System.Collections.Generic;
using System.Windows.Media.Imaging;
using System.Linq;

using Fiesta_Client.API;
using Ocya_Launcher;

namespace Fiesta_Client.Panels
{
    public partial class Main : UserControl
    {
        private MainWindow MainHandle;
        private Boolean InstallGame;
        private String InstallLocation;

        private BackgroundWorker Worker;

        public Main(MainWindow MW, Boolean IG, String IL)
        {
            InitializeComponent();

            MainHandle = MW;
            InstallGame = IG;
            InstallLocation = IL;

            if (!File.Exists(String.Format("{0}\\Launcher\\Background.mp4", AppDomain.CurrentDomain.BaseDirectory))) { File.WriteAllBytes(String.Format("{0}\\Launcher\\Background.mp4", AppDomain.CurrentDomain.BaseDirectory), Properties.Resources.Background); }

            if (!File.Exists(String.Format("{0}\\Launcher\\Music.mp3", AppDomain.CurrentDomain.BaseDirectory)))
            {
                File.WriteAllBytes(String.Format("{0}\\Launcher\\Music.mp3", AppDomain.CurrentDomain.BaseDirectory), Properties.Resources.Music);

                Process.Start(String.Format("{0}\\{1} Launcher.exe", AppDomain.CurrentDomain.BaseDirectory, Web.Settings()["Server-Name"]));

                Environment.Exit(0);
            }

            if (File.Exists(String.Format("{0}\\Launcher\\Music.txt", AppDomain.CurrentDomain.BaseDirectory))) { DisableMusic.Dispatcher.BeginInvoke((Action)(() => { DisableMusic.Background = GetBrush("MusicEnable"); })); }
        }

        private void UserControl_Initialized(object sender, EventArgs e) { StartWorker(); }

        private void StartWorker()
        {
            Worker = new BackgroundWorker();
            Worker.DoWork += Worker_DoWork;
            Worker.RunWorkerCompleted += Worker_RunWorkerCompleted;

            Worker.RunWorkerAsync();
        }

        private void Worker_DoWork(object sender, DoWorkEventArgs e)
        {
            if (!Directory.Exists(String.Format("{0}\\Launcher\\", AppDomain.CurrentDomain.BaseDirectory))) { Directory.CreateDirectory(String.Format("{0}\\Launcher\\", AppDomain.CurrentDomain.BaseDirectory)); }
            if (!File.Exists(String.Format("{0}\\Launcher\\Version.txt", AppDomain.CurrentDomain.BaseDirectory)))
            {
                StreamWriter Writer = new StreamWriter(File.Open(String.Format("{0}\\Launcher\\Version.txt", AppDomain.CurrentDomain.BaseDirectory), FileMode.Create, FileAccess.ReadWrite, FileShare.None));
                Writer.WriteLine(0);
                Writer.Flush();
                Writer.Close();
            }

            if (Environment.CommandLine.Contains("-Update"))
            {
                Thread.Sleep(2000);

                Process[] RunningEditors = Process.GetProcessesByName("Nyx Launcher").Where(ID => ID.Id != AppDomain.CurrentDomain.Id).ToArray();

                foreach (Process RunningEditor in RunningEditors) { RunningEditor.Kill(); }

                File.Delete(String.Format("{0}\\Nyx Launcher.exe", AppDomain.CurrentDomain.BaseDirectory));
                File.Copy(String.Format("{0}\\Update.exe", AppDomain.CurrentDomain.BaseDirectory), String.Format("{0}\\Nyx Launcher.exe", AppDomain.CurrentDomain.BaseDirectory));

                Process.Start(String.Format("{0}\\Nyx Launcher.exe", AppDomain.CurrentDomain.BaseDirectory));

                Environment.Exit(0);
            }

            try
            {
                Information.Dispatcher.BeginInvoke((Action)(() => { Information.Content = "Checking for update..."; }));

                Int32 Version = Web.LauncherVersion();

                if (Version != Properties.Settings.Default.Version)
                {
                    DownloadLoop(Web.Settings()["Update-Exe"], "Update.exe", true);

                    Information.Dispatcher.BeginInvoke((Action)(() => { Information.Content = "Update complete"; }));
                    Progress.Dispatcher.BeginInvoke((Action)(() => { Progress.Value = 100; }));

                    Process StartNewUpdate = new Process();
                    StartNewUpdate.StartInfo.Arguments = "-Update";
                    StartNewUpdate.StartInfo.FileName = String.Format("{0}\\Update.exe", AppDomain.CurrentDomain.BaseDirectory);
                    StartNewUpdate.Start();

                    Environment.Exit(0);
                }
                else { }
            }
            catch { }

            Int32 ClientVersion = Convert.ToInt32(File.ReadAllLines(String.Format("{0}\\Launcher\\Version.txt", AppDomain.CurrentDomain.BaseDirectory))[0]);
            Int32 ServerVersion = Web.ServerVersion();

            String PatchesFolder = Web.Settings()["Patches-Folder"];

            while (ClientVersion != ServerVersion)
            {
                DownloadLoop(PatchesFolder, String.Format("Patch{0}.rar", ClientVersion + 1), false);

                Extract PatchExtract = new Extract();
                PatchExtract.FileName = String.Format("Patch{0}", ClientVersion + 1);
                PatchExtract.FilePath = String.Format("{0}\\Temp\\Patch{1}.rar", AppDomain.CurrentDomain.BaseDirectory, ClientVersion + 1);
                PatchExtract.Progress = Progress;
                PatchExtract.Information = Information;
                PatchExtract.StartExtract();

                ClientVersion = ClientVersion + 1;
            }

            File.Delete(String.Format("{0}\\Launcher\\Version.txt", AppDomain.CurrentDomain.BaseDirectory));

            using (var Writer = new StreamWriter(String.Format("{0}\\Launcher\\Version.txt", AppDomain.CurrentDomain.BaseDirectory)))
            {
                Writer.WriteLine(ClientVersion);
                Writer.Flush();
                Writer.Close();
            }

            //
            Information.Dispatcher.BeginInvoke((Action)(() => { Information.Content = "Checking client..."; }));

            Files_Completed.Dispatcher.BeginInvoke((Action)(() => { Files_Completed.Visibility = System.Windows.Visibility.Visible; }));
            Files_Left.Dispatcher.BeginInvoke((Action)(() => { Files_Left.Visibility = System.Windows.Visibility.Visible; }));
            Files_Total.Dispatcher.BeginInvoke((Action)(() => { Files_Total.Visibility = System.Windows.Visibility.Visible; }));

            List<String> ClientFiles = new List<String>();
            ClientFiles.AddRange(Web.ClientFiles());

            Progress.Dispatcher.BeginInvoke((Action)(() => { Progress.Maximum = ClientFiles.Count; }));

            foreach (String PatchFile in ClientFiles.ToArray())
            {
                Information.Dispatcher.BeginInvoke((Action)(() => { Information.Content = String.Format("Checking: {0}", PatchFile); }));

                if (File.Exists(String.Format("{0}\\{1}", AppDomain.CurrentDomain.BaseDirectory, PatchFile))) { ClientFiles.Remove(PatchFile); }

                Progress.Dispatcher.BeginInvoke((Action)(() => { Progress.Value = Progress.Value + 1; }));
            }

            Files_Total.Dispatcher.BeginInvoke((Action)(() => { Files_Total.Content = String.Format("Total Files: {0}", ClientFiles.Count); }));

            Progress.Dispatcher.BeginInvoke((Action)(() => { Progress.Maximum = 100; }));

            Int32 FilesLeft = ClientFiles.Count;
            Int32 FilesCompleted = 0;

            String ClientFolder = Web.Settings()["Client-Folder"];

            foreach (String PatchFile in ClientFiles.ToArray())
            {
                Files_Left.Dispatcher.BeginInvoke((Action)(() => { Files_Left.Content = String.Format("Files Left: {0}", FilesLeft); }));
                Files_Completed.Dispatcher.BeginInvoke((Action)(() => { Files_Completed.Content = String.Format("Completed Files: {0}", FilesCompleted); }));

                DownloadLoop(ClientFolder, PatchFile, true);

                FilesLeft--;
                FilesCompleted++;
            }

            Files_Completed.Dispatcher.BeginInvoke((Action)(() => { Files_Completed.Visibility = System.Windows.Visibility.Hidden; }));
            Files_Left.Dispatcher.BeginInvoke((Action)(() => { Files_Left.Visibility = System.Windows.Visibility.Hidden; }));
            Files_Total.Dispatcher.BeginInvoke((Action)(() => { Files_Total.Visibility = System.Windows.Visibility.Hidden; }));
        }

        private void DownloadLoop(String StartPath, String ClientFile, Boolean Move)
        {
            if (!File.Exists(String.Format("{0}\\{1}", AppDomain.CurrentDomain.BaseDirectory, ClientFile)))
            {
                if (File.Exists(String.Format("{0}\\Temp\\{1}", AppDomain.CurrentDomain.BaseDirectory, Path.GetFileName(ClientFile)))) { File.Delete(String.Format("{0}\\Temp\\{1}", AppDomain.CurrentDomain.BaseDirectory, Path.GetFileName(ClientFile))); }

                Download FileDownloader = new Download();
                FileDownloader.Address = new Uri(String.Format("{0}/{1}", StartPath, ClientFile));
                FileDownloader.FileName = Path.GetFileNameWithoutExtension(ClientFile);
                FileDownloader.Information = Information;
                FileDownloader.Progress = Progress;
                FileDownloader.SavePath = String.Format("{0}\\Temp\\{1}", AppDomain.CurrentDomain.BaseDirectory, Path.GetFileName(ClientFile));
                FileDownloader.StartDownload();

                while (!FileDownloader.HasErrored && !FileDownloader.IsFinished) { Thread.Sleep(1000); }

                if (FileDownloader.HasErrored)
                {
                    Information.Dispatcher.BeginInvoke((Action)(() => { Information.Content = String.Format("Error occured while getting {0}, attempting to restart in 5 seconds.", Path.GetFileName(ClientFile)); }));

                    Thread.Sleep(5000);

                    DownloadLoop(StartPath, ClientFile, Move);
                }

                if (FileDownloader.IsFinished)
                {
                    if (!Directory.Exists(String.Format("{0}\\{1}", AppDomain.CurrentDomain.BaseDirectory, ClientFile))) { Directory.CreateDirectory(String.Format("{0}\\{1}", AppDomain.CurrentDomain.BaseDirectory, ClientFile.Replace(Path.GetFileName(ClientFile), ""))); }

                    if (Move) { File.Move(String.Format("{0}\\Temp\\{1}", AppDomain.CurrentDomain.BaseDirectory, Path.GetFileName(ClientFile)), String.Format("{0}\\{1}", AppDomain.CurrentDomain.BaseDirectory, ClientFile)); }
                }
            }
            else
            {
                File.Delete(String.Format("{0}\\{1}", AppDomain.CurrentDomain.BaseDirectory, ClientFile));

                DownloadLoop(StartPath, ClientFile, Move);
            }
        }

        private void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            Files_Total.Dispatcher.BeginInvoke((Action)(() => { Files_Total.Visibility = Visibility.Hidden; }));
            Files_Left.Dispatcher.BeginInvoke((Action)(() => { Files_Left.Visibility = Visibility.Hidden; }));
            Files_Completed.Dispatcher.BeginInvoke((Action)(() => { Files_Completed.Visibility = Visibility.Hidden; }));

            Information.Dispatcher.BeginInvoke((Action)(() => { Information.Content = "Client patched & ready to use!"; }));

            Play.Dispatcher.BeginInvoke((Action)(() => { Play.IsEnabled = true; }));
            Play.Dispatcher.BeginInvoke((Action)(() => { Play.Background = GetBrush("Play"); }));

            Resolution.Dispatcher.BeginInvoke((Action)(() => { Resolution.IsEnabled = true; }));

            Resolution.Dispatcher.BeginInvoke((Action)(() => { Progress.Value = 100; }));
        }

        private ImageBrush GetBrush(String FileName)
        {
            ImageBrush BaseBrush = new ImageBrush();
            Image BaseImage = new Image();
            BaseImage.Source = new BitmapImage(new Uri(String.Format("pack://application:,,,/Fiesta_Client;component/Resources/{0}.png", FileName)));

            BaseBrush.ImageSource = BaseImage.Source;

            return BaseBrush;
        }

        private void Register_MouseEnter(object sender, MouseEventArgs e)
        {
            Register.Dispatcher.BeginInvoke((Action)(() => { Register.Background = GetBrush("Register_Glow"); }));
        }

        private void Register_MouseLeave(object sender, MouseEventArgs e)
        {
            Register.Dispatcher.BeginInvoke((Action)(() => { Register.Background = GetBrush("Register"); }));
        }

        private void Register_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { Process.Start(Web.Settings()["Register-URL"]); }

        private void Forums_MouseEnter(object sender, MouseEventArgs e)
        {
            Forums.Dispatcher.BeginInvoke((Action)(() => { Forums.Background = GetBrush("Forums_Glow"); }));
        }

        private void Forums_MouseLeave(object sender, MouseEventArgs e)
        {
            Forums.Dispatcher.BeginInvoke((Action)(() => { Forums.Background = GetBrush("Forums"); }));
        }

        private void Forums_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { Process.Start(Web.Settings()["Forums-URL"]); }

        private void Buy_MouseEnter(object sender, MouseEventArgs e)
        {
            Buy.Dispatcher.BeginInvoke((Action)(() => { Buy.Background = GetBrush("Buy_Glow"); }));
        }

        private void Buy_MouseLeave(object sender, MouseEventArgs e)
        {
            Buy.Dispatcher.BeginInvoke((Action)(() => { Buy.Background = GetBrush("Buy"); }));
        }

        private void Buy_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { MainHandle.ShowBuy(); }

        private void News_MouseEnter(object sender, MouseEventArgs e)
        {
            News.Dispatcher.BeginInvoke((Action)(() => { News.Background = GetBrush("News_Glow"); }));
        }

        private void News_MouseLeave(object sender, MouseEventArgs e)
        {
            News.Dispatcher.BeginInvoke((Action)(() => { News.Background = GetBrush("News"); }));
        }

        private void News_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { Process.Start(Web.Settings()["News-URL"]); }

        private void Repair_MouseEnter(object sender, MouseEventArgs e)
        {
            Repair.Dispatcher.BeginInvoke((Action)(() => { Repair.Background = GetBrush("Repair_Glow"); }));
        }

        private void Repair_MouseLeave(object sender, MouseEventArgs e)
        {
            Repair.Dispatcher.BeginInvoke((Action)(() => { Repair.Background = GetBrush("Repair"); }));
        }

        private void Repair_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            MessageBoxResult test = MessageBox.Show("are you sure you wan't to repatch? This will set back to patch 0 and patch all patches again", "Nyx launcher", MessageBoxButton.YesNo, MessageBoxImage.Error);

            if (test == MessageBoxResult.Yes)
            {
                File.Delete(String.Format("{0}\\Launcher\\Version.txt", AppDomain.CurrentDomain.BaseDirectory));

                Process.Start(String.Format("{0}\\Nyx Launcher.exe", AppDomain.CurrentDomain.BaseDirectory));

                Environment.Exit(0);
            }
        }

        private void Resolution_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { MainHandle.ShowResolution(); }

        private void Play_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            Process StartClient = new Process();
            StartClient.StartInfo.Arguments = String.Format("-i {0} -p {1}", Web.Settings()["Client-IP"], Web.Settings()["Client-Port"]);
            StartClient.StartInfo.FileName = Web.Settings()["Client-EXE"];
            StartClient.Start();

            Environment.Exit(0);
        }

        private void DisableMusic_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (!File.Exists(String.Format("{0}\\Launcher\\Music.txt", AppDomain.CurrentDomain.BaseDirectory)))
            {
                File.Create(String.Format("{0}\\Launcher\\Music.txt", AppDomain.CurrentDomain.BaseDirectory)).Close();

                DisableMusic.Dispatcher.BeginInvoke((Action)(() => { DisableMusic.Background = GetBrush("MusicEnable"); }));

                MainHandle.StopMusic();
            }
            else
            {
                File.Delete(String.Format("{0}\\Launcher\\Music.txt", AppDomain.CurrentDomain.BaseDirectory));

                DisableMusic.Dispatcher.BeginInvoke((Action)(() => { DisableMusic.Background = GetBrush("MusicDisable"); }));

                MainHandle.PlayMusic();
            }
        }
    }
}
