using Apewer.Surface;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace Apewer.Tray
{

    /// <summary>托盘。</summary>
    class Tray
    {

        Form _form = null;
        NotifyIcon _icon = null;

        Tray(Action action)
        {
            _tray = this;
            _form = new Form();
            _form.FormBorderStyle = FormBorderStyle.None;
            _form.Size = new Size(0, 0);
            _form.StartPosition = FormStartPosition.CenterScreen;
            _form.ShowInTaskbar = false;
            _form.Text = "";
            _form.Paint += (s, e) =>
            {
                if (_form.Visible)
                {
                    _form.Visible = false;
                    action?.Invoke();
                }
            };
            Application.Run(_form);
        }

        static Tray _tray = null;
        static object _locker = new object();

        /// <summary>托盘图标。</summary>
        public NotifyIcon Icon { get => _tray?._icon; }

        /// <summary>在托盘线程中执行方法。</summary>
        public static void Invoke(Action action, bool async = false)
        {
            lock (_locker)
            {
                if (action == null) return;
                if (_tray == null) return;
                if (async) _tray?._form.BeginInvoke(new Action(action));
                else _tray?._form.Invoke(new Action(action));
            }
        }

        /// <summary>在托盘线程中执行方法。</summary>
        public static void BeginInvoke(Action action)
        {
            lock (_locker)
            {
                if (action == null) return;
                if (_tray == null) return;
                _tray?._form.BeginInvoke(new Action(action));
            }
        }

        /// <summary>启动托盘,阻塞当前线程。</summary>
        [STAThread]
        public static void Run(Action after = null)
        {
            lock (_locker)
            {
                if (_tray != null) return;


                FormsUtility.StartInitialization();
                FormsUtility.CrossThread();
                new Tray(after);
            }
        }

        /// <summary>退出托盘。</summary>
        public static void Exit()
        {
            lock (_locker)
            {
                if (_tray != null)
                {
                    if (_tray._icon != null)
                    {
                        _tray._icon.Visible = false;
                        _tray._icon.Dispose();
                    }
                    _tray._form.Close();
                    _tray._form.Dispose();
                }
                _tray = null;
            }
        }

        /// <summary>显示托盘图标。</summary>
        public static void ShowIcon(Icon icon = null)
        {
            lock (_locker)
            {
                if (_tray == null) return;
                if (_tray._icon == null) _tray._icon = new NotifyIcon();
                _tray._icon.Icon = icon;
                _tray._icon.Visible = true;
            }
        }

        /// <summary>隐藏托盘图标。</summary>
        public static void HideIcon()
        {
            lock (_locker)
            {
                if (_tray == null) return;
                if (_tray._icon == null) return;
                _tray._icon.Visible = false;
            }
        }

        /// <summary>显示消息对话框。</summary>
        public static void MessageBox(string text, string caption = "", Action ok = null)
        {
            Invoke(() =>
            {
                System.Windows.Forms.MessageBox.Show(text, caption, MessageBoxButtons.OK);
                ok?.Invoke();
            });
        }

        /// <summary>显示确认对话框。</summary>
        public static void YesNo(string text, string caption = "", Action yes = null, Action no = null)
        {
            Invoke(() =>
            {
                var result = System.Windows.Forms.MessageBox.Show(text, caption, MessageBoxButtons.YesNo);
                if (result == DialogResult.Yes) yes?.Invoke();
                else if (result == DialogResult.No) no?.Invoke();
            });
        }

        /// <summary>显示打开文件对话框。</summary>
        public static void OpenFile(string title = null, Action<string[]> ok = null, Action cancel = null, bool multiselect = false, string filter = null, string directory = null)
        {
            Invoke(() =>
            {
                DialogResult result;
                string[] paths;
                using (var dialog = new OpenFileDialog())
                {
                    if (!string.IsNullOrEmpty(title)) dialog.Title = title;
                    if (!string.IsNullOrEmpty(filter)) dialog.Filter = filter;
                    if (!string.IsNullOrEmpty(directory)) dialog.InitialDirectory = directory;
                    dialog.Multiselect = multiselect;
                    result = dialog.ShowDialog();
                    paths = dialog.FileNames;
                }
                if (result == DialogResult.OK) ok?.Invoke(paths);
                else if (result == DialogResult.Cancel) cancel?.Invoke();
            });
        }

        /// <summary>显示保存文件对话框。</summary>
        public static void SaveFile(string title = null, Action<string> ok = null, Action cancel = null, string filter = null, string directory = null)
        {
            Invoke(() =>
            {
                DialogResult result;
                string path;
                using (var dialog = new SaveFileDialog())
                {
                    if (!string.IsNullOrEmpty(title)) dialog.Title = title;
                    if (!string.IsNullOrEmpty(filter)) dialog.Filter = filter;
                    if (!string.IsNullOrEmpty(directory)) dialog.InitialDirectory = directory;
                    result = dialog.ShowDialog();
                    path = dialog.FileName;
                }
                if (result == DialogResult.OK) ok?.Invoke(path);
                else if (result == DialogResult.Cancel) cancel?.Invoke();
            });
        }

        /// <summary>显示选择文件夹对话框。</summary>
        public static void SelectFolder(string description = null, Action<string> ok = null, Action cancel = null)
        {
            Invoke(() =>
            {
                DialogResult result;
                string path;
                using (var dialog = new FolderBrowserDialog())
                {
                    if (!string.IsNullOrEmpty(description)) dialog.Description = description;
                    dialog.ShowNewFolderButton = true;
                    result = dialog.ShowDialog();
                    path = dialog.SelectedPath;
                }
                if (result == DialogResult.OK) ok?.Invoke(path);
                else if (result == DialogResult.Cancel) cancel?.Invoke();
            });
        }

    }

}