using System;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
using Katteker.Properties;

namespace Katteker
{
    internal sealed partial class UpdateWindow : Form
    {
        private readonly ReleaseEntry _entry;
        private readonly UpdateManager _updateManager;

        /// <summary>
        ///     The Update Window
        /// </summary>
        internal UpdateWindow(UpdateManager updateManager, ReleaseEntry entry)
        {
            _updateManager = updateManager;
            _entry = entry;
            Font = SystemFonts.MessageBoxFont;
            Application.EnableVisualStyles();
            if (Environment.OSVersion.Version.Major >= 6)
                NativeMethods.SetProcessDPIAware();
            InitializeComponent();
        }

        private string Changelog => _updateManager.ChangelogFilename;

        private string PublishPath => _updateManager.UrlOrPath;

        /// <inheritdoc />
        /// <summary>
        ///     Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing) components?.Dispose();
            base.Dispose(disposing);
        }

        private void CloseBtn_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void MaximizeBtn_Click(object sender, EventArgs e)
        {
            WindowState = WindowState != FormWindowState.Maximized ? FormWindowState.Maximized : FormWindowState.Normal;
        }

        private void MinimizeBtn_Click(object sender, EventArgs e)
        {
            WindowState = FormWindowState.Minimized;
        }

        private void Titlebar_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left && e.Clicks >= 2)
            {
                MaximizeBtn_Click(sender, e);
                return;
            }

            if (e.Button != MouseButtons.Left) return;
            NativeMethods.ReleaseCapture();
            NativeMethods.SendMessage(Handle, NativeMethods.WM_NCLBUTTONDOWN, NativeMethods.HTCAPTION, 0);
        }


        private void UpdateWindow_Activated(object sender, EventArgs e)
        {
            titleLayoutPanel.BackColor = SystemColors.ControlDarkDark;
            titleLayoutPanel.ForeColor = SystemColors.Control;
        }

        private void UpdateWindow_Deactivate(object sender, EventArgs e)
        {
            titleLayoutPanel.BackColor = SystemColors.Control;
            titleLayoutPanel.ForeColor = SystemColors.ControlText;
        }

        private async void UpdateWindow_Load(object sender, EventArgs e)
        {
            var changelogContent = "No changelog provided.";
            if (Changelog != null)
            {
                changelogContent = await ChangelogHelper.LoadChangelogAsync(Changelog, PublishPath).ConfigureAwait(false);
            }

            changelogContent = changelogContent.ChangelogAsHtml(Path.GetExtension(Changelog));
            InvokeOnGui(() => changelogBrowser.DocumentText = changelogContent);

            if (_entry == null)
            {
                WriteTitle(Resources.No_update_available);
            }
            else
            {
                var latest = _entry.Version;
                WriteTitle(Resources.You_can_update_to_Version + latest);
                InvokeOnGui(() => updBtn.Visible = true);
            }
        }

        private async void UpdBtn_Click(object sender, EventArgs e)
        {
            InvokeOnGui(() => progressBar1.Visible = true);

            try
            {
                var progress = new Progress<int>(x => InvokeOnGui(() => progressBar1.Value = x));
                await _updateManager.UpdateAppAsync(progress).ConfigureAwait(false);

                WriteTitle(Resources.You_re_up_to_date);
                var messResult = MessageBox.Show(
                    Resources.Installed_new_Version,
                    Resources.New_Version,
                    MessageBoxButtons.YesNo,
                    MessageBoxIcon.Question);
                if (messResult == DialogResult.Yes)
                {
                    InvokeOnGui(() =>
                    {
                        DialogResult = DialogResult.OK;
                        Close();
                    });
                    return;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(Resources.CouldNotUpdateYourApplication + Environment.NewLine + ex.Message,
                    Resources.Updater, MessageBoxButtons.OK, MessageBoxIcon.Error);
                WriteTitle(Resources.Updater);
            }

            InvokeOnGui(() =>
            {
                progressBar1.Visible = false;
                updBtn.Visible = false;
            });
        }

        private void WriteTitle(string text)
        {
            InvokeOnGui(() =>
            {
                Text = text;
                titlebar.Text = text;
            });
        }

        private void InvokeOnGui(Action action)
        {
            if (Disposing || IsDisposed) return;
            if (InvokeRequired)
            {
                Invoke(action);
            }
            else
            {
                action();
            }
        }
    }
}