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 HttpRequest _httpRequest;
        private readonly MainViewModel _mainViewModel;
        private readonly FileConfig _fileConfig;
        private DirectoryInfo _lDir;

        public MainWindow()
        {
            _httpRequest = new HttpRequest();
            _mainViewModel = new MainViewModel();
            _fileConfig = new FileConfig();
            InitializeComponent();
            Initialize();
        }

        private void Initialize()
        {
            try
            {
                lblTotalQtd.Content = "0.0MB";
                lblTotalAtualizadoQtd.Content = "0.0MB";
                lblAtualQtd.Content = "0.0MB";
                lblDownloadSpeed.Visibility = Visibility.Hidden;
                lblDownloadSpeedQtd.Visibility = Visibility.Hidden;
                lblWellcome.Visibility = Visibility.Hidden;
                lblFileDownloading.Visibility = Visibility.Hidden;
                lblFileDownloadingName.Visibility = Visibility.Hidden;
                wbSlide.Visibility = Visibility.Hidden;
                _mainViewModel.IsChecking = false;
                _mainViewModel.IsUpdating = false;
                _mainViewModel.IsLogged = false;
                _mainViewModel.Lang = _fileConfig.GetLanguage();
                DataContext = _mainViewModel;
                wbSlide.Navigate(Configuration.Default.ServerIP + Configuration.Default.LauncherNewsUrl);
                AccountModel.Username = _fileConfig.GetUsername();
                _lDir = new DirectoryInfo(Environment.CurrentDirectory);

                if (AccountModel.Username != "")
                {
                    textUsername.Text = AccountModel.Username;
                }

                if (!File.Exists("LauncherVersionSetting"))
                {
                    _fileConfig.SetLauncherIsChecked(EncryptionHelper.Encrypt("FALSE"));
                }

                if (EncryptionHelper.Decrypt(this._fileConfig.GetLauncherIsChecked()) != "FALSE")
                {
                    return;
                }

                Process.Start(new ProcessStartInfo
                {
                    WorkingDirectory = _lDir.Parent.FullName,
                    FileName = "LauncherUpdater.exe",
                    CreateNoWindow = false
                });
            }
            catch (Exception ex)
            {
                Logger.WriteLog(ex.Message);
            }
        }

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

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

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

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

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

                CheckClientFiles();
            }
        }

        private async Task GetUpdate()
        {
            var mainWindow = this;
            try
            {
                var httpRequest = new HttpRequest();
                if (!Directory.Exists(Configuration.Default.DownloadDir))
                {
                    Directory.CreateDirectory(Configuration.Default.DownloadDir);
                }

                var getVersionResponse = JsonConvert.DeserializeObject<ResponseLauncherVersion>(
                    await httpRequest.GetLauncherVersionAsync(AccountModel.Token, AccountModel.Username)
                );
                var 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 = (HttpRequest) 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);
                    HttpRequest httpRequest = new HttpRequest();
                    if (!Directory.Exists(Configuration.Default.DownloadDir))
                        Directory.CreateDirectory(Configuration.Default.DownloadDir);
                    ResponseListLauncherFiles listLauncherFiles =
                        JsonConvert.DeserializeObject<ResponseListLauncherFiles>(
                            await httpRequest.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")
                            {
                                var lblTotalQtd = mainWindow.lblTotalQtd;
                                var num1 = Math.Round(file.Size / 1024.0, 2);
                                var str1 = num1 + "MB";
                                lblTotalQtd.Content = str1;
                                Label lblAtualQtd = mainWindow.lblAtualQtd;
                                num1 = Math.Round(file.Size / 1024.0, 2);
                                var str2 = num1 + "MB";
                                lblAtualQtd.Content = str2;
                                var num2 = await mainWindow.DownloadArchiveAsync(file.Filename,
                                    Configuration.Default.DownloadDir, file.Url)
                                    ? 1
                                    : 0;
                                var num3 = file.Size / file.Size * 656.0;
                                totalDownloaded += file.Size;
                                mainWindow.progressBar.Width += (int) num3;
                                mainWindow.ExtractFiles();
                                var totalAtualizadoQtd = mainWindow.lblTotalAtualizadoQtd;
                                num1 = Math.Round(totalDownloaded / 1024.0, 2);
                                var str3 = num1 + "MB";
                                totalAtualizadoQtd.Content = str3;
                            }
                        }
                    }

                    mainWindow._mainViewModel.IsUpdating = false;
                    mainWindow.DataContext = mainWindow._mainViewModel;
                    mainWindow.lblTotalQtd.Content = "0.0MB";
                    mainWindow.lblTotalAtualizadoQtd.Content = "0.0MB";
                    mainWindow.lblAtualQtd.Content = "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 = "Escolha um idioma para continuar!";
            }
            catch (Exception ex)
            {
                Logger.WriteLog(ex.Message);
            }
        }
    }
}