using System.Threading.Tasks;
using System.Windows.Forms;

namespace FizzyLauncher
{
    public class FileSessionManager
    {
        public delegate void OnNewSessionEvent(FileSessionManager sender);
        public delegate Task<bool> OnSaveSessionEvent(FileSessionManager sender, string filename, bool showNotices = true);
        public delegate Task<bool> OnLoadSessionEvent(FileSessionManager sender, string filename);
        public delegate Task OnClearSessionEvent(FileSessionManager sender);


        public string SessionFilename { get; set; } = null;

        public string NewSessionPromptTitle { get; set; } = "New session";
        public string OpenSessionPromptTitle { get; set; } = "Open session";
        public string CloseSessionPromptTitle { get; set; } = "Close session";
        public string SaveExistingSession { get; set; } = "Save existing session?";

        public OpenFileDialog OpenFileDialog { get; set; } = null;
        public SaveFileDialog SaveFileDialog { get; set; } = null;

        public OnNewSessionEvent OnNewSession { get; set; } = null;
        public OnSaveSessionEvent OnSaveSession { get; set; } = null;
        public OnLoadSessionEvent OnLoadSession { get; set; } = null;
        public OnClearSessionEvent OnClearSession { get; set; } = null;


        public async Task NewSession()
        {
            if (string.IsNullOrWhiteSpace(this.SessionFilename))
            {
                this.SessionFilename = null;

                PerformNewSession();
            }
            else
            {
                var result = MessageBox.Show(this.SaveExistingSession, this.NewSessionPromptTitle, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
                if (result == DialogResult.Yes)
                {
                    var result2 = await PerformSaveSession(this.SessionFilename, false);
                    if (result2)
                    {
                        this.SessionFilename = null;

                        PerformNewSession();
                    }
                }
                else if (result == DialogResult.No)
                {
                    this.SessionFilename = null;

                    PerformNewSession();
                }
                else if (result == DialogResult.Cancel)
                {
                    return;
                }
            }
        }

        public async Task OpenSession(string filename)
        {
            this.SessionFilename = filename;

            if (string.IsNullOrWhiteSpace(this.SessionFilename))
            {
                await this.OpenSession();
            }
            else
            {
                await PerformLoadSession(this.SessionFilename);
            }
        }

        public async Task OpenSession()
        {
            if (string.IsNullOrWhiteSpace(this.SessionFilename))
            {
                if (this.OpenFileDialog.ShowDialog() == DialogResult.OK)
                {
                    this.SessionFilename = this.OpenFileDialog.FileName;

                    await PerformLoadSession(this.SessionFilename);
                }
            }
            else
            {
                var result = MessageBox.Show(this.SaveExistingSession, this.OpenSessionPromptTitle, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
                if (result == DialogResult.Yes)
                {
                    if (await PerformSaveSession(this.SessionFilename, false))
                    {
                        if (this.OpenFileDialog.ShowDialog() == DialogResult.OK)
                        {
                            this.SessionFilename = this.OpenFileDialog.FileName;

                            await PerformLoadSession(this.SessionFilename);
                        }
                    }
                }
                else if (result == DialogResult.No)
                {
                    if (this.OpenFileDialog.ShowDialog() == DialogResult.OK)
                    {
                        this.SessionFilename = this.OpenFileDialog.FileName;

                        await PerformLoadSession(this.SessionFilename);
                    }
                }
                else if (result == DialogResult.Cancel)
                {
                    return;
                }
            }
        }

        public async Task SaveSession()
        {
            if (string.IsNullOrWhiteSpace(this.SessionFilename))
            {
                await this.SaveAsSession();
            }
            else
            {
                await PerformSaveSession(this.SessionFilename, true);
            }
        }

        public async Task<bool> SaveAsSession()
        {
            if (this.SaveFileDialog.ShowDialog() == DialogResult.OK)
            {
                bool result = await PerformSaveSession(this.SaveFileDialog.FileName);
                if (result)
                {
                    this.SessionFilename = this.SaveFileDialog.FileName;
                }

                return result;
            }

            return false;
        }

        public async Task CloseSession()
        {
            if (string.IsNullOrWhiteSpace(this.SessionFilename))
            {
                this.SessionFilename = null;

                await PerformClearSession();
            }
            else
            {
                var result = MessageBox.Show(this.SaveExistingSession, this.CloseSessionPromptTitle, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
                if (result == DialogResult.Yes)
                {
                    bool result2 = await PerformSaveSession(this.SessionFilename, false);
                    if (result2)
                    {
                        this.SessionFilename = null;

                        await PerformClearSession();
                    }
                }
                else if (result == DialogResult.No)
                {
                    this.SessionFilename = null;

                    await PerformClearSession();
                }
                else if (result == DialogResult.Cancel)
                {
                    return;
                }
            }
        }


        private void PerformNewSession() => this.OnNewSession?.Invoke(this);

        private async Task<bool> PerformSaveSession(string filename, bool showNotices = true)
        {
            if (this.OnSaveSession == null)
            {
                return false;
            }

            return await this.OnSaveSession?.Invoke(this, filename, showNotices);
        }

        private async Task<bool> PerformLoadSession(string filename)
        {
            if (this.OnLoadSession == null)
            {
                return false;
            }

            return await this.OnLoadSession?.Invoke(this, filename);
        }

        private async Task PerformClearSession() => this.OnClearSession?.Invoke(this);


    }
}
