using LauncherIcarus.Daemon;
using LauncherIcarus.Daemon.HTTP;
using LauncherIcarus.Model;
using LauncherIcarus.ResponseModel;
using Newtonsoft.Json;
using System;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Net;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace LauncherIcarus
{
    public partial class MainWindow : Window
    {
        private readonly HTTPREQ httpRequest;
        private readonly MainViewModel mainViewModel;
        private readonly FileConfig fileConfig;
        private DirectoryInfo lDir;

        public MainWindow()
        {
            this.httpRequest = new HTTPREQ();
            this.mainViewModel = new MainViewModel();
            this.fileConfig = new FileConfig();
            this.InitializeComponent();
            this.Initialize();
        }

        private void Initialize()
        {
            try
            {
                this.lblTotalQtd.Content = (object) "0.0MB";
                this.lblTotalAtualizadoQtd.Content = (object) "0.0MB";
                this.lblAtualQtd.Content = (object) "0.0MB";
                this.lblDownloadSpeed.Visibility = Visibility.Hidden;
                this.lblDownloadSpeedQtd.Visibility = Visibility.Hidden;
                this.lblWellcome.Visibility = Visibility.Hidden;
                this.lblFileDownloading.Visibility = Visibility.Hidden;
                this.lblFileDownloadingName.Visibility = Visibility.Hidden;
                this.wbSlide.Visibility = Visibility.Hidden;
                this.mainViewModel.IsChecking = false;
                this.mainViewModel.IsUpdating = false;
                this.mainViewModel.IsLogged = false;
                this.mainViewModel.Lang = this.fileConfig.GetLanguage();
                this.DataContext = (object) this.mainViewModel;
                this.wbSlide.Navigate(Configuration.Default.ServerIP + Configuration.Default.LauncherNewsUrl);
                AccountModel.Username = this.fileConfig.GetUsername();
                this.lDir = new DirectoryInfo(Environment.CurrentDirectory);
                this.InstallRedist();
                if (AccountModel.Username.ToString() != "")
                    this.textUsername.Text = AccountModel.Username.ToString();
                if (!System.IO.File.Exists("LauncherVersionSetting"))
                    this.fileConfig.SetLauncherIsChecked(EncryptionHelper.Encrypt("FALSE"));
                if (!(EncryptionHelper.Decrypt(this.fileConfig.GetLauncherIsChecked()) == "FALSE"))
                    return;
                Process.Start(new ProcessStartInfo()
                {
                    WorkingDirectory = this.lDir.Parent.FullName,
                    FileName = "LauncherUpdater.exe",
                    CreateNoWindow = false
                });
            }
            catch (Exception ex)
            {
                Logger.WriteLog(ex.Message);
            }
        }

        private void InstallRedist()
        {
            if (System.IO.File.Exists("RedistInstall"))
                return;
            try
            {
                string str = string.Format(this.lDir.Parent.FullName + "\\Tools\\Redist");
                Process process = new Process();
                process.StartInfo.WorkingDirectory = str;
                process.StartInfo.FileName = "Installer.cmd";
                process.StartInfo.Arguments = string.Format("10");
                process.StartInfo.CreateNoWindow = false;
                process.Start();
                process.WaitForExit();
                this.fileConfig.SetRedistIsInstaled();
            }
            catch (Exception ex)
            {
                Logger.WriteLog(ex.Message);
            }
        }

        private void buttonMinimizer_Click(object sender, RoutedEventArgs e) =>
            this.WindowState = WindowState.Minimized;

        private void buttonClose_Click(object sender, RoutedEventArgs e) => this.Close();

        private async void buttonAccess_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                this.lblWellcome.Visibility = Visibility.Hidden;
                ResponseLogin responseLogin = JsonConvert.DeserializeObject<ResponseLogin>(
                    await this.httpRequest.LoginAsync(this.textUsername.Text, this.textPassword.Password.ToString()));
                if (responseLogin.Code == 0)
                {
                    this.fileConfig.SetUsername(responseLogin.Accountinfo.Username);
                    AccountModel.Token = responseLogin.Token;
                    AccountModel.Username = responseLogin.Accountinfo.Username;
                    AccountModel.Version = responseLogin.Accountinfo.Version;
                    this.fileConfig.SetLauncherIsChecked(EncryptionHelper.Encrypt("FALSE"));
                    this.lblWellcome.Visibility = Visibility.Visible;
                    this.lblWellcome.Content = (object) ("Seja bem vindo " + AccountModel.Username);
                    this.lblMsgStatus.Visibility = Visibility.Hidden;
                    this.inputUsername.Visibility = Visibility.Hidden;
                    this.inputPassword.Visibility = Visibility.Hidden;
                    this.textUsername.Visibility = Visibility.Hidden;
                    this.textPassword.Visibility = Visibility.Hidden;
                    this.buttonAccess.Visibility = Visibility.Hidden;
                    this.wbSlide.Visibility = Visibility.Visible;
                    this.mainViewModel.IsLogged = true;
                    this.GetUpdate();
                }

                this.lblMsgStatus.Content = (object) responseLogin.message;
            }
            catch (Exception ex)
            {
                this.lblMsgStatus.Content = (object) ex.Message;
                Logger.WriteLog(ex.Message);
            }
        }

        private void buttonVerify_Click(object sender, RoutedEventArgs e)
        {
            if (!this.mainViewModel.IsLogged)
            {
                this.lblMsgStatus.Content = (object) "Antes de verificar os arquivos faça login!";
            }
            else
            {
                if (this.mainViewModel.IsUpdating || this.mainViewModel.IsChecking)
                    return;
                this.CheckClientFiles();
            }
        }

        private async Task GetUpdate()
        {
            MainWindow mainWindow = this;
            try
            {
                HTTPREQ httpRequest = new HTTPREQ();
                if (!Directory.Exists(Configuration.Default.DownloadDir))
                    Directory.CreateDirectory(Configuration.Default.DownloadDir);
                ResponseLauncherVersion getVersionResponse =
                    JsonConvert.DeserializeObject<ResponseLauncherVersion>(
                        await httpRequest.GetLauncherVersionAsync(AccountModel.Token, AccountModel.Username));
                ResponseListLauncherFiles getLauncherListResponse =
                    JsonConvert.DeserializeObject<ResponseListLauncherFiles>(
                        await httpRequest.GetLauncherListFilesAsync(AccountModel.Token,
                            getVersionResponse.UpdaterVersion.ToString()));
                if (getLauncherListResponse.TotalBytes > 0.0)
                {
                    double totalDownloaded = 0.0;
                    mainWindow.progressBar.Width = 0.0;
                    mainWindow.mainViewModel.IsUpdating = true;
                    mainWindow.lblDownloadSpeed.Visibility = Visibility.Visible;
                    mainWindow.lblDownloadSpeedQtd.Visibility = Visibility.Visible;
                    mainWindow.lblFileDownloading.Visibility = Visibility.Visible;
                    mainWindow.lblFileDownloadingName.Visibility = Visibility.Visible;
                    int LastVersion = 0;
                    int ClientVersion = getVersionResponse.UpdaterVersion;
                    mainWindow.lblTotalQtd.Content =
                        (object) (Math.Round(getLauncherListResponse.TotalBytes / 1024.0, 2).ToString() + "MB");
                    foreach (Files file in getLauncherListResponse.File)
                    {
                        LastVersion = (int) file.version;
                        double num1;
                        if (LastVersion > ClientVersion)
                        {
                            Label lblAtualQtd = mainWindow.lblAtualQtd;
                            num1 = Math.Round(file.size / 1024.0, 2);
                            string str = num1.ToString() + "MB";
                            lblAtualQtd.Content = (object) str;
                            int num2 = await mainWindow.DownloadArchiveAsync(file.filename,
                                Configuration.Default.DownloadDir, file.url)
                                ? 1
                                : 0;
                        }

                        double num3 = file.size / getLauncherListResponse.TotalBytes * 656.0;
                        totalDownloaded += file.size;
                        mainWindow.progressBar.Width += (double) (int) num3;
                        mainWindow.ExtractFiles();
                        Label totalAtualizadoQtd = mainWindow.lblTotalAtualizadoQtd;
                        num1 = Math.Round(totalDownloaded / 1024.0, 2);
                        string str1 = num1.ToString() + "MB";
                        totalAtualizadoQtd.Content = (object) str1;
                    }

                    JsonConvert.DeserializeObject<ResponseLauncherVersion>(
                        await httpRequest.UpdateLauncherVersionAsync(AccountModel.Token, LastVersion.ToString(),
                            AccountModel.Username));
                }

                mainWindow.mainViewModel.IsUpdating = false;
                mainWindow.DataContext = (object) mainWindow.mainViewModel;
                mainWindow.lblTotalQtd.Content = (object) "0.0MB";
                mainWindow.lblTotalAtualizadoQtd.Content = (object) "0.0MB";
                mainWindow.lblAtualQtd.Content = (object) "0.0MB";
                mainWindow.lblDownloadSpeed.Visibility = Visibility.Hidden;
                mainWindow.lblDownloadSpeedQtd.Visibility = Visibility.Hidden;
                mainWindow.lblFileDownloading.Visibility = Visibility.Hidden;
                mainWindow.lblFileDownloadingName.Visibility = Visibility.Hidden;
                httpRequest = (HTTPREQ) null;
                getVersionResponse = (ResponseLauncherVersion) null;
                getLauncherListResponse = (ResponseListLauncherFiles) null;
            }
            catch (Exception ex)
            {
                Logger.WriteLog(ex.Message);
            }
        }

        public async Task CheckClientFiles()
        {
            MainWindow mainWindow = this;
            try
            {
                mainWindow.progressBar.Width = 0.0;
                mainWindow.mainViewModel.IsChecking = true;
                double totalDownloaded = 0.0;
                Crc32 c = new Crc32();
                ResponseListLauncherFiles get =
                    JsonConvert.DeserializeObject<ResponseListLauncherFiles>(
                        await mainWindow.httpRequest.GetClientFilesCheckListAsync(AccountModel.Token));
                if (get.TotalBytes > 0.0)
                {
                    Label lblTotalQtd = mainWindow.lblTotalQtd;
                    double num1 = Math.Round(get.TotalBytes / 1024.0, 2);
                    string str1 = num1.ToString() + "MB";
                    lblTotalQtd.Content = (object) str1;
                    mainWindow.lblDownloadSpeed.Visibility = Visibility.Visible;
                    mainWindow.lblDownloadSpeedQtd.Visibility = Visibility.Visible;
                    mainWindow.lblFileDownloading.Visibility = Visibility.Visible;
                    mainWindow.lblFileDownloadingName.Visibility = Visibility.Visible;
                    foreach (Files k in get.File)
                    {
                        string filename = k.filename;
                        string empty = string.Empty;
                        string path = mainWindow.lDir.Parent.FullName + "\\" + k.filename.Replace("/", "\\");
                        Label lblAtualQtd = mainWindow.lblAtualQtd;
                        num1 = Math.Round(k.size / 1024.0, 2);
                        string str2 = num1.ToString() + "MB";
                        lblAtualQtd.Content = (object) str2;
                        if (System.IO.File.Exists(path))
                        {
                            using (FileStream inputStream = System.IO.File.Open(path, FileMode.Open))
                            {
                                foreach (byte num2 in c.ComputeHash((Stream) inputStream))
                                    empty += num2.ToString("x2").ToLower();
                            }

                            if (k.crc32 != empty)
                            {
                                int num3 = await mainWindow.DownloadArchiveAsync(filename,
                                    mainWindow.lDir.Parent.FullName, k.url)
                                    ? 1
                                    : 0;
                            }
                        }
                        else
                        {
                            int num4 = await mainWindow.DownloadArchiveAsync(filename, mainWindow.lDir.Parent.FullName,
                                k.url)
                                ? 1
                                : 0;
                        }

                        totalDownloaded += k.size;
                        double num5 = k.size / get.TotalBytes * 656.0;
                        Label totalAtualizadoQtd = mainWindow.lblTotalAtualizadoQtd;
                        num1 = Math.Round(totalDownloaded / 1024.0, 2);
                        string str3 = num1.ToString() + "MB";
                        totalAtualizadoQtd.Content = (object) str3;
                        mainWindow.progressBar.Width += Math.Round(num5, 0);
                    }
                }

                mainWindow.mainViewModel.IsChecking = false;
                mainWindow.DataContext = (object) mainWindow.mainViewModel;
                mainWindow.lblTotalQtd.Content = (object) "0.0MB";
                mainWindow.lblTotalAtualizadoQtd.Content = (object) "0.0MB";
                mainWindow.lblAtualQtd.Content = (object) "0.0MB";
                mainWindow.lblDownloadSpeed.Visibility = Visibility.Hidden;
                mainWindow.lblDownloadSpeedQtd.Visibility = Visibility.Hidden;
                mainWindow.lblFileDownloading.Visibility = Visibility.Hidden;
                mainWindow.lblFileDownloadingName.Visibility = Visibility.Hidden;
                c = (Crc32) null;
                get = (ResponseListLauncherFiles) null;
            }
            catch (Exception ex)
            {
                Logger.WriteLog(ex.Message);
            }
        }

        private async Task<bool> DownloadArchiveAsync(
            string filename,
            string downloadPath,
            string url)
        {
            DateTime _startedAt = DateTime.Now;
            DownloadProgressChangedEventHandler changedEventHandler = (DownloadProgressChangedEventHandler) ((s, e) =>
            {
                if (_startedAt == new DateTime())
                {
                    _startedAt = DateTime.Now;
                }
                else
                {
                    TimeSpan timeSpan = DateTime.Now - _startedAt;
                    if (timeSpan.TotalSeconds <= 0.0)
                        return;
                    this.lblDownloadSpeedQtd.Content = (object) string.Format("{0} MB/s",
                        (object) Math.Round((double) e.BytesReceived / (timeSpan.TotalSeconds * 1000000.0), 2));
                    this.lblFileDownloadingName.Content = (object) filename;
                }
            });
            DownloadDataCompletedEventHandler completedEventHandler =
                (DownloadDataCompletedEventHandler) ((s, e) => { });
            int num1 = filename.IndexOf("/");
            string str = filename;
            string fileName;
            if (num1 > 0)
            {
                int num2 = 0;
                string[] strArray = filename.Split(new string[1]
                {
                    "/"
                }, StringSplitOptions.None);
                downloadPath += "\\";
                for (int index = 0; index < strArray.Length - 1; ++index)
                {
                    downloadPath = downloadPath + strArray[index] + "\\";
                    num2 = index;
                }

                if (!Directory.Exists(downloadPath))
                    Directory.CreateDirectory(downloadPath);
                fileName = downloadPath + strArray[num2 + 1].Replace("/", "\\");
                Logger.WriteLog(filename);
            }
            else
                fileName = downloadPath + filename;

            using (WebClient webClient = new WebClient())
            {
                webClient.DownloadProgressChanged += changedEventHandler;
                webClient.DownloadDataCompleted += completedEventHandler;
                await webClient.DownloadFileTaskAsync(new Uri(Configuration.Default.ServerIP + url), fileName);
            }

            return true;
        }

        private void ExtractFiles()
        {
            try
            {
                foreach (string file in Directory.GetFiles(Configuration.Default.DownloadDir, "*.zip"))
                {
                    using (ZipArchive zipArchive = ZipFile.Open(file, ZipArchiveMode.Read))
                    {
                        foreach (ZipArchiveEntry entry in zipArchive.Entries)
                        {
                            if (entry.Length > 0L || entry.Name != "")
                            {
                                entry.ExtractToFile(Path.Combine(this.lDir.Parent.FullName, entry.FullName), true);
                            }
                            else
                            {
                                string[] strArray = entry.FullName.Split(new string[1]
                                {
                                    "/"
                                }, StringSplitOptions.None);
                                string path2 = "";
                                for (int index = 0; index < strArray.Length; ++index)
                                    path2 = path2 + strArray[index] + "/";
                                if (!Directory.Exists(Path.Combine(this.lDir.Parent.FullName, path2)))
                                    Directory.CreateDirectory(Path.Combine(this.lDir.Parent.FullName, path2));
                            }
                        }
                    }

                    System.IO.File.Delete(file);
                }
            }
            catch (Exception ex)
            {
                Logger.WriteLog(ex.Message);
            }
        }

        private void buttonStart_Click(object sender, RoutedEventArgs e)
        {
            if (!mainViewModel.IsLogged || mainViewModel.IsUpdating || mainViewModel.IsChecking)
            {
                return;
            }

            try
            {
                var folder = lDir.Parent?.FullName.Replace("Launcher", "");
                var sw = new StreamWriter(folder + @"\start.bat");
                sw.WriteLine(
                    $"cd {folder} && start Bin64/Launcher.exe /i:{AccountModel.Token} /r:123456 /O /u:3913056 /m:P");
                sw.Close();
                var param = folder + @"\start.bat";
                Process.Start(param);

                Environment.Exit(0);
            }
            catch (Exception ex)
            {
                Logger.WriteLog(ex.Message);
            }
        }

        private void Window_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.LeftButton != MouseButtonState.Pressed)
                return;
            this.DragMove();
        }

        private async void cmbLanguage_DropDownClosed(object sender, EventArgs e)
        {
            MainWindow mainWindow = this;
            try
            {
                if (mainWindow.fileConfig.GetLanguage() != mainWindow.mainViewModel.Lang &&
                    mainWindow.mainViewModel.Lang != string.Empty)
                {
                    mainWindow.fileConfig.SetLanguage(mainWindow.mainViewModel.Lang);
                    HTTPREQ httpreq = new HTTPREQ();
                    if (!Directory.Exists(Configuration.Default.DownloadDir))
                        Directory.CreateDirectory(Configuration.Default.DownloadDir);
                    ResponseListLauncherFiles listLauncherFiles =
                        JsonConvert.DeserializeObject<ResponseListLauncherFiles>(
                            await httpreq.GetLauncherTranslateAsync());
                    if (listLauncherFiles.TotalBytes > 0.0)
                    {
                        double totalDownloaded = 0.0;
                        mainWindow.progressBar.Width = 0.0;
                        mainWindow.mainViewModel.IsUpdating = true;
                        mainWindow.lblDownloadSpeed.Visibility = Visibility.Visible;
                        mainWindow.lblDownloadSpeedQtd.Visibility = Visibility.Visible;
                        mainWindow.lblFileDownloading.Visibility = Visibility.Visible;
                        mainWindow.lblFileDownloadingName.Visibility = Visibility.Visible;
                        foreach (Files file in listLauncherFiles.File)
                        {
                            if (file.filename == mainWindow.mainViewModel.Lang.ToLower() + ".zip")
                            {
                                Label lblTotalQtd = mainWindow.lblTotalQtd;
                                double num1 = Math.Round(file.size / 1024.0, 2);
                                string str1 = num1.ToString() + "MB";
                                lblTotalQtd.Content = (object) str1;
                                Label lblAtualQtd = mainWindow.lblAtualQtd;
                                num1 = Math.Round(file.size / 1024.0, 2);
                                string str2 = num1.ToString() + "MB";
                                lblAtualQtd.Content = (object) str2;
                                int num2 = await mainWindow.DownloadArchiveAsync(file.filename,
                                    Configuration.Default.DownloadDir, file.url)
                                    ? 1
                                    : 0;
                                double num3 = file.size / file.size * 656.0;
                                totalDownloaded += file.size;
                                mainWindow.progressBar.Width += (double) (int) num3;
                                mainWindow.ExtractFiles();
                                Label totalAtualizadoQtd = mainWindow.lblTotalAtualizadoQtd;
                                num1 = Math.Round(totalDownloaded / 1024.0, 2);
                                string str3 = num1.ToString() + "MB";
                                totalAtualizadoQtd.Content = (object) str3;
                            }
                        }
                    }

                    mainWindow.mainViewModel.IsUpdating = false;
                    mainWindow.DataContext = (object) mainWindow.mainViewModel;
                    mainWindow.lblTotalQtd.Content = (object) "0.0MB";
                    mainWindow.lblTotalAtualizadoQtd.Content = (object) "0.0MB";
                    mainWindow.lblAtualQtd.Content = (object) "0.0MB";
                    mainWindow.lblDownloadSpeed.Visibility = Visibility.Hidden;
                    mainWindow.lblDownloadSpeedQtd.Visibility = Visibility.Hidden;
                    mainWindow.lblFileDownloading.Visibility = Visibility.Hidden;
                    mainWindow.lblFileDownloadingName.Visibility = Visibility.Hidden;
                }
                else
                    mainWindow.lblMsgStatus.Content = (object) "Escolha um idioma para continuar!";
            }
            catch (Exception ex)
            {
                Logger.WriteLog(ex.Message);
            }
        }
    }
}