using System;
using System.IO;
using System.Collections.Generic;
using System.Globalization;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.Storage.Pickers;
using Windows.Storage;
using System.Net.Mail;
using Windows.UI.Popups;
using Windows.System;
using System.Threading.Tasks;
using Windows.UI.Xaml.Media;
using Windows.UI;
using System.IO.Compression;
using System.Xml;
using Windows.ApplicationModel.Resources;

namespace FoxTube.Pages.SettingsPages
{
    public sealed partial class Translate : Page
    {
        //TODO: Localize page
        ResourceLoader resources = ResourceLoader.GetForCurrentView("Translate");
        StorageFile submission;
        public Translate()
        {
            InitializeComponent();
            foreach (CultureInfo culture in CultureInfo.GetCultures(CultureTypes.AllCultures))
                if (culture.ThreeLetterISOLanguageName != "rus" && culture.ThreeLetterISOLanguageName != "eng" && culture.IsNeutralCulture)
                    LangList.Items.Add(culture);
        }

        private async void export_Click(object sender, RoutedEventArgs e)
        {
            FileSavePicker picker = new FileSavePicker();
            picker.CommitButtonText = resources.GetString("/Translate/exportPicker");
            picker.DefaultFileExtension = ".zip";
            picker.SuggestedFileName = "foxtube_langpack_" + ((CultureInfo)LangList.SelectedItem).ThreeLetterISOLanguageName;
            picker.SuggestedStartLocation = PickerLocationId.Desktop;
            picker.FileTypeChoices.Add(resources.GetString("/Translate/langpackScheme"), new List<string>() { ".zip" });

            StorageFile file = await picker.PickSaveFileAsync();
            if (file == null)
                return;

            await (await StorageFile.GetFileFromApplicationUriAsync("ms-appx:///Assets/Data/Package.zip".ToUri())).CopyAndReplaceAsync(file);

            await Launcher.LaunchFileAsync(file);
        }

        private void LangList_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            greenResult.Visibility = Visibility.Collapsed;
            certification.Visibility = Visibility.Collapsed;
            upload.Visibility = Visibility.Visible;

            upload.IsEnabled = true;
            export.IsEnabled = true;
        }

        private async void upload_Click(object sender, RoutedEventArgs e)
        {
            FileOpenPicker picker = new FileOpenPicker()
            {
                CommitButtonText = resources.GetString("/Translate/submit/Content"),
                SuggestedStartLocation = PickerLocationId.Desktop
            };
            picker.FileTypeFilter.Clear();
            picker.FileTypeFilter.Add(".zip");

            StorageFile file = await picker.PickSingleFileAsync();
            if (file == null)
                return;

            export.IsEnabled = false;
            upload.Visibility = Visibility.Collapsed;
            certification.Visibility = Visibility.Visible;

            (certificationStatus.Children[0] as FontIcon).Glyph = "\xECC5";
            (certificationStatus.Children[0] as FontIcon).Foreground = new SolidColorBrush(Colors.Orange);
            (certificationStatus.Children[1] as TextBlock).Text = resources.GetString("/Translate/inprogress");

            submit.IsEnabled = log.IsEnabled = chooseFile.IsEnabled = true;
            submit.Visibility = Visibility.Collapsed;
            log.Visibility = Visibility.Collapsed;
            chooseFile.Visibility = Visibility.Collapsed;
            uploadingProgress.Visibility = Visibility.Visible;

            CertificationReport report = await PerformCetification(file);
            if (report.Status == CertificationReport.CertificationStatus.Failed)
            {
                (certificationStatus.Children[0] as FontIcon).Glyph = "\xEB90";
                (certificationStatus.Children[0] as FontIcon).Foreground = new SolidColorBrush(Colors.Red);
                (certificationStatus.Children[1] as TextBlock).Text = resources.GetString("/Translate/failed");
                chooseFile.Visibility = Visibility.Visible;
                log.Visibility = Visibility.Visible;
                log.Tag = report.Report;
                export.IsEnabled = true;
                uploadingProgress.Visibility = Visibility.Collapsed;
                return;
            }

            submission = file;

            (certificationStatus.Children[0] as FontIcon).Glyph = "\xEC61";
            (certificationStatus.Children[0] as FontIcon).Foreground = new SolidColorBrush(Colors.Green);
            (certificationStatus.Children[1] as TextBlock).Text = resources.GetString("/Translate/passed");

            export.IsEnabled = true;
            submit.Visibility = Visibility.Visible;
            chooseFile.Visibility = Visibility.Visible;
            uploadingProgress.Visibility = Visibility.Collapsed;
        }

        async Task<CertificationReport> PerformCetification(StorageFile file)
        {
            CertificationReport report = new CertificationReport { Status = CertificationReport.CertificationStatus.Passed };

            string log = string.Empty;
            StorageFolder folder = await ApplicationData.Current.RoamingFolder.CreateFolderAsync("Package certification");
            StorageFile submissionSample = await folder.CreateFileAsync("sample.zip");
            await file.CopyAndReplaceAsync(submissionSample);
            ZipFile.ExtractToDirectory(submissionSample.Path, folder.Path);

            List<string> filesDescriptions = new List<string>
            {
                "About", "Cards", "Channel", "Chat", "CommentsPage", "Downloads", "General", "Home", "Inbox",
                "LoadingPage", "Main", "Methods", "Playlist", "Search", "Settings", "Translate", "VideoPage"
            };

            foreach(string i in filesDescriptions)
                if (await folder.TryGetItemAsync($"{i}.resw") == null)
                {
                    log += $"- {resources.GetString("/Translate/file")} '{i}.resw' {resources.GetString("/Translate/notfound")}\n";
                    report.Status = CertificationReport.CertificationStatus.Failed;
                }
                else
                {
                    try { new XmlDocument().Load(await (await folder.GetFileAsync(i + ".resw")).OpenStreamForReadAsync()); }
                    catch
                    {
                        log += $"- {resources.GetString("/Translate/file")} '{i}.resw': {resources.GetString("/Translate/failedRead")}";
                        report.Status = CertificationReport.CertificationStatus.Failed;
                    }
                }

            if(report.Status == CertificationReport.CertificationStatus.Failed)
            {
                report.Report = await ApplicationData.Current.RoamingFolder.CreateFileAsync("certReport.txt", CreationCollisionOption.ReplaceExisting);
                await FileIO.WriteTextAsync(report.Report, log);
            }

            await folder.DeleteAsync(StorageDeleteOption.PermanentDelete);

            return report;
        }

        private async void Log_Click(object sender, RoutedEventArgs e)
        {
            await Launcher.LaunchFileAsync(((Button)sender).Tag as StorageFile);
        }

        private async void Submit_Click(object sender, RoutedEventArgs e)
        {
            uploadingProgress.Visibility = Visibility.Visible;
            submit.IsEnabled = false;
            chooseFile.IsEnabled = false;

            MailMessage msg = new MailMessage();
            msg.To.Add("michael.xfox@outlook.com");
            msg.From = new MailAddress(SecretsVault.EmailCredential.UserName, "FoxTube Automatic response system");
            msg.Subject = "[Automatic message] FoxTube language pack contribution";
            msg.Body = $@"Language: {((CultureInfo)LangList.SelectedItem).EnglishName}
Language code: {((CultureInfo)LangList.SelectedItem).ThreeLetterISOLanguageName}
-----------------
Contributor info:
Username: {(SecretsVault.UserInfo == null ? "/UNAUTHORIZED_USER/" : SecretsVault.UserInfo.Name)}
E-mail: {(SecretsVault.UserInfo == null ? "/UNAUTHORIZED_USER/" : SecretsVault.UserInfo.Email)}";
            msg.Attachments.Add(new Attachment(await submission.OpenStreamForReadAsync(), "submission.zip"));

            SmtpClient client = new SmtpClient("smtp.gmail.com", 587);
            client.EnableSsl = true;
            client.Credentials = SecretsVault.EmailCredential;

            upload.IsEnabled = false;
            export.IsEnabled = false;
            uploadingProgress.Visibility = Visibility.Visible;
            try
            {
                client.Send(msg);
                if(!string.IsNullOrWhiteSpace(SecretsVault.UserInfo.Email))
                {
                    msg = new MailMessage();
                    msg.To.Add(SecretsVault.UserInfo.Email);
                    msg.From = new MailAddress(SecretsVault.EmailCredential.UserName, resources.GetString("/Translate/username"));
                    msg.Subject = resources.GetString("/Translate/subject");
                    msg.Body = $@"{SecretsVault.UserInfo.Name},
{resources.GetString("/Translate/body")}";
                    client.Send(msg);
                }
                greenResult.Visibility = Visibility.Visible;
                submitNotification.Visibility = Visibility.Collapsed;
            }
            catch
            {
                MessageDialog message = new MessageDialog(resources.GetString("/Translate/failedSend/Body"), resources.GetString("/Translate/failedSend/Header"));
                await message.ShowAsync();
                export.IsEnabled = true;
                upload.IsEnabled = true;
                submit.IsEnabled = true;
                chooseFile.IsEnabled = true;
            }
            uploadingProgress.Visibility = Visibility.Collapsed;
        }
    }

    public class CertificationReport
    {
        public enum CertificationStatus { Passed, Failed, Processing }
        public CertificationStatus Status { get; set; }
        public StorageFile Report { get; set; }
    }
}
