using System;
using System.ComponentModel;
using System.Windows.Forms;
using NotepadEnhanced.GUI.Controls;
using NotepadEnhanced.GUI.Forms;
using NotepadEnhanced.Helpers;
using NotepadEnhanced.Localization;

namespace NotepadEnhanced.AppState
{
    public partial class SettingsForm : Form
    { 
        private readonly MainForm _frmMain;
        private readonly SupportedCultures _supportedCultures = new SupportedCultures();
        private bool _loadingLanguages = true;
        // Keep track of the last selected index as the SelectedIndexChanged event
        // will raise even if the index selected is the same. We do not want this behaviour
        private int _lastLanguageIndex;

        public SettingsForm(MainForm frmMain)
        {
            _frmMain = frmMain;
            InitializeComponent();
            UpdateControlStates();
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            // All settings that are changed through the GUI,  immediate effect on the app should be saved here
            UserSettings.Instance.ReadingHorizPadding = (int)nudHorizPadding.Value;
            UserSettings.Instance.ReadingVertPadding = (int)nudVertPadding.Value;
            UserSettings.Instance.ReadingWidth = (int)nudReadingWidth.Value;
            UserSettings.Instance.ReadingViewTopMost = chkReadingTopmost.Checked;
            UserSettings.Instance.Signature = txtSigInsert.Text;
            UserSettings.Instance.SingleInstance = chkSingleInstance.Checked;
            UserSettings.Instance.AddTabOnStart = chkAddTabOnStart.Checked;
            UserSettings.Instance.ShowLargeFileWarning = chkFileWarning.Checked;
            UserSettings.Instance.PromptToRestore = chkRestorePrompt.Checked;
            UserSettings.Instance.RecentFilesEnabled = chkRecentFilesEnabled.Checked;
            UserSettings.Instance.AddTitleToPrint = chkAddTitle.Checked;
            UserSettings.Instance.AutoWordSelection = chkAutoWordSelection.Checked;

            foreach (PlainTextBox box in _frmMain.PlainTextBoxes)
            {
                box.AutoWordSelection = UserSettings.Instance.AutoWordSelection;
            }

            UserSettings.Instance.RecentQueSize = (int)nudMaxRecents.Value;
            RecentFileQue.LimitQue();

            base.OnClosing(e);
        }

        private void UpdateControlStates()
        {
            this.SuspendLayout();
            lblFont.Text = UserSettings.Instance.Font.GetBasicInfo();
            txtSigInsert.Text = UserSettings.Instance.Signature;
            pickerTextColor.PickedColor = UserSettings.Instance.FontColor;
            pickerBackColor.PickedColor = UserSettings.Instance.BackColor;
            pickerLnNumStyleColor.PickedColor = UserSettings.Instance.LineNumStyleColor;
            pickerLnNumForeColor.PickedColor = UserSettings.Instance.LineNumForeColor;
            nudMaxRecents.Value = UserSettings.Instance.RecentQueSize;
            chkSingleInstance.Checked = UserSettings.Instance.SingleInstance;
            chkAddTabOnStart.Checked = UserSettings.Instance.AddTabOnStart;
            chkRecentFilesEnabled.Checked = UserSettings.Instance.RecentFilesEnabled;
            chkAddTitle.Checked = UserSettings.Instance.AddTitleToPrint;
            chkFileWarning.Checked = UserSettings.Instance.ShowLargeFileWarning;
            chkSelectionMargin.Checked = UserSettings.Instance.ShowSelectionMargin;
            chkMultilineTabs.Checked = UserSettings.Instance.MultiLineTabs;
            chkRestorePrompt.Checked = UserSettings.Instance.PromptToRestore;
            chkTrackSelection.Checked = UserSettings.Instance.TrackSelection;
            nudScrollSpeed.Value = UserSettings.Instance.LineNumScrollSpeed;
            chkAutoWordSelection.Checked = UserSettings.Instance.AutoWordSelection;
            // Reading settings
            chkReadingTopmost.Checked = UserSettings.Instance.ReadingViewTopMost;
            nudReadingWidth.Value = UserSettings.Instance.ReadingWidth;
            pickerReadBackColor.PickedColor = UserSettings.Instance.ReadingBackColor;
            pickerReadForeColor.PickedColor = UserSettings.Instance.ReadingForeColor;
            pickerWindowColor.PickedColor = UserSettings.Instance.ReadingBackColor;
            lblReadingFont.Text = UserSettings.Instance.ReadingFont.GetBasicInfo();
            nudVertPadding.Value = UserSettings.Instance.ReadingVertPadding;
            nudHorizPadding.Value = UserSettings.Instance.ReadingHorizPadding;

            ListAvailableLanguages();

            switch (UserSettings.Instance.LineNumStyle)
            {
                case LineNumberStyle.None: comboLnNumStyle.SelectedIndex = 0; break;
                case LineNumberStyle.OffsetColors: comboLnNumStyle.SelectedIndex = 1; break;
                case LineNumberStyle.Boxed: comboLnNumStyle.SelectedIndex = 2; break;
            }

            // We are going to click the checkBox in opposed to checking them, as we want to make sure 
            // the logic that unchecks the other checkboxes run
            switch (UserSettings.Instance.PrintTitleAlign)
            {
                case 0: chkLeft_Click(null, EventArgs.Empty); break;
                case 1: chkMiddle_Click(null, EventArgs.Empty); break;
                case 2: chkRight_Click(null, EventArgs.Empty); break;
                default: chkLeft_Click(null, EventArgs.Empty); break;
            }

            LoadColorPickers();
            this.ResumeLayout();
        }

        private void LoadColorPickers()
        {
            var customColors = new[]
                {
                    UserSettings.Instance.ReadingForeColor,
                    UserSettings.Instance.ReadingBackColor,
                    UserSettings.Instance.FontColor,
                    UserSettings.Instance.BackColor,
                    UserSettings.Instance.LineNumStyleColor,
                    UserSettings.Instance.LineNumForeColor
                };

            pickerTextColor.CustomColors = customColors;
            pickerBackColor.CustomColors = customColors;
            pickerReadForeColor.CustomColors = customColors;
            pickerReadBackColor.CustomColors = customColors;
            pickerWindowColor.CustomColors = customColors;
            pickerLnNumStyleColor.CustomColors = customColors;
            pickerLnNumForeColor.CustomColors = customColors;

            pickerTextColor.PickedColor = UserSettings.Instance.FontColor;
            pickerBackColor.PickedColor = UserSettings.Instance.BackColor;
            pickerReadForeColor.PickedColor = UserSettings.Instance.ReadingForeColor;
            pickerReadBackColor.PickedColor = UserSettings.Instance.ReadingBackColor;
            pickerWindowColor.PickedColor = UserSettings.Instance.ReadingBackColor;
            pickerLnNumStyleColor.PickedColor = UserSettings.Instance.LineNumStyleColor;
            pickerLnNumForeColor.PickedColor = UserSettings.Instance.LineNumForeColor;
        }

        private void pickerTextColor_ColorPicked(object sender, EventArgs e)
        {
            UserSettings.Instance.FontColor = pickerTextColor.PickedColor;
            pickerTextColor.PickedColor = pickerTextColor.PickedColor;

            foreach (PlainTextBox textBox in _frmMain.PlainTextBoxes)
                textBox.ForeColor = pickerTextColor.PickedColor;
        }

        private void ListAvailableLanguages()
        {
            comboLanguageSelect.SuspendLayout();
            comboLanguageSelect.Items.Clear();
            comboLanguageSelect.Items.AddRange(_supportedCultures.ToStringArray());
            comboLanguageSelect.SelectedIndex = _supportedCultures.DefaultCultureIndex;
            comboLanguageSelect.ResumeLayout();
            _lastLanguageIndex = comboLanguageSelect.SelectedIndex;
            _loadingLanguages = false;
        }

        #region Print Title
        private void chkLeft_Click(object sender, EventArgs e)
        {
            UserSettings.Instance.PrintTitleAlign = 0;
            chkLeft.Checked = true;
            chkMiddle.Checked = chkRight.Checked = false;
        }

        private void chkMiddle_Click(object sender, EventArgs e)
        {
            UserSettings.Instance.PrintTitleAlign = 1;
            chkMiddle.Checked = true;
            chkRight.Checked = chkLeft.Checked = false;
        }

        private void chkRight_Click(object sender, EventArgs e)
        {
            UserSettings.Instance.PrintTitleAlign = 2;
            chkRight.Checked = true;
            chkLeft.Checked = chkMiddle.Checked = false;
        }
        #endregion

        #region Other 
        private void comboLanguageSelect_SelectedIndexChanged(object sender, EventArgs e)
        {
            // Only apply language settings if the user selects a different language
            if (!_loadingLanguages && comboLanguageSelect.SelectedIndex != _lastLanguageIndex)
            {
                int index = comboLanguageSelect.SelectedIndex;
                UserSettings.Instance.Culture = _supportedCultures.All[index].Name;
                ShowRestartMessage();
                _lastLanguageIndex = comboLanguageSelect.SelectedIndex;
            }
        }

        private static void ShowRestartMessage()
        {
            DialogResult result = MsgBox.Show(Strings.RestartPrompt, MessageBoxIcon.Question, MessageBoxButtons.YesNo);

            if (result == DialogResult.Yes)
            {
                UserSettings.Instance.Save();
                Application.Restart();
            }
        }

        private void chkSelectionMargin_Click(object sender, EventArgs e)
        {
            UserSettings.Instance.ShowSelectionMargin = chkSelectionMargin.Checked;

            foreach (PlainTextBox box in _frmMain.PlainTextBoxes)
                box.ShowSelectionMargin = UserSettings.Instance.ShowSelectionMargin;
        }

        private void chkMultilineTabs_Click(object sender, EventArgs e)
        {
            UserSettings.Instance.MultiLineTabs = chkMultilineTabs.Checked;
            _frmMain.SetMultilineTabbing();
        }

        private void chkTrackSelection_Click(object sender, EventArgs e)
        {
            UserSettings.Instance.TrackSelection = chkTrackSelection.Checked;
            _frmMain.TrackCaretOnTabControl = chkTrackSelection.Checked;
        }
        #endregion

        #region Fonts and Appearance
        private void btnPickFont_Click(object sender, EventArgs e)
        {
            using (FontDialog dlgFont = new FontDialog())
            {
                dlgFont.ShowEffects = false;
                dlgFont.Font = UserSettings.Instance.Font;

                try
                {
                    if (dlgFont.ShowDialog() != DialogResult.OK) return;

                    foreach (PlainTextBox plainTextBox in _frmMain.PlainTextBoxes)
                        plainTextBox.Font = dlgFont.Font;

                    UserSettings.Instance.Font = dlgFont.Font;
                    lblFont.Text = dlgFont.Font.GetBasicInfo();
                }
                catch (ArgumentException ex)
                {
                    MsgBox.Show(ex.Message);
                }
            }
        }

        private void pickerBackColor_ColorPicked(object sender, EventArgs e)
        {
            UserSettings.Instance.BackColor = pickerBackColor.PickedColor;

            foreach (PlainTextBox textBox in _frmMain.PlainTextBoxes)
                textBox.BackColor = pickerBackColor.PickedColor;
        }
        #endregion

        #region Reading View
        private void btnPickReadingFont_Click(object sender, EventArgs e)
        {
            using (FontDialog dlgFont = new FontDialog())
            {
                dlgFont.ShowEffects = false;
                dlgFont.Font = UserSettings.Instance.ReadingFont;

                try
                {
                    if (dlgFont.ShowDialog() == DialogResult.OK)
                    {
                        UserSettings.Instance.ReadingFont = dlgFont.Font;
                        lblReadingFont.Text = dlgFont.Font.GetBasicInfo();
                    }
                }
                catch (ArgumentException ex)
                {
                    MsgBox.Show(ex.Message);
                }
            }
        }

        private void pickerReadForeColor_ColorPicked(object sender, EventArgs e)
        {
            UserSettings.Instance.ReadingForeColor = pickerReadForeColor.PickedColor;
        }

        private void pickerReadBackColor_ColorPicked(object sender, EventArgs e)
        {
            UserSettings.Instance.ReadingBackColor = pickerReadBackColor.PickedColor;
        }

        private void pickerWindowColor_ColorPicked(object sender, EventArgs e)
        {
            UserSettings.Instance.ReadingBackColor = pickerWindowColor.PickedColor;
        }
        #endregion

        #region Line Numbering
        private void pickerLnNumStyleColor_ColorPicked(object sender, EventArgs e)
        {
            UserSettings.Instance.LineNumStyleColor = pickerLnNumStyleColor.PickedColor;

            foreach (LineNumberStrip strip in _frmMain.LineNumberStrips)
            {
                strip.OffsetColor = pickerLnNumStyleColor.PickedColor;
                strip.BoxedLineColor = pickerLnNumStyleColor.PickedColor;
            }
        }

        private void pickerLnNumForeColor_ColorPicked(object sender, EventArgs e)
        {
            UserSettings.Instance.LineNumForeColor = pickerLnNumForeColor.PickedColor;

            foreach (LineNumberStrip strip in _frmMain.LineNumberStrips)
                strip.ForeColor = pickerLnNumForeColor.PickedColor;
        }

        private void comboLnNumStyle_SelectedIndexChanged(object sender, EventArgs e)
        {
            switch (comboLnNumStyle.SelectedIndex)
            {
                case 0: UserSettings.Instance.LineNumStyle = LineNumberStyle.None;
                    break;

                case 1: UserSettings.Instance.LineNumStyle = LineNumberStyle.OffsetColors;
                    break;

                case 2: UserSettings.Instance.LineNumStyle = LineNumberStyle.Boxed;
                    break;
            }

            foreach (var strip in _frmMain.LineNumberStrips) 
                strip.Style = UserSettings.Instance.LineNumStyle;
        }

        private void nudScrollSpeed_ValueChanged(object sender, EventArgs e)
        {
            UserSettings.Instance.LineNumScrollSpeed = (int)nudScrollSpeed.Value;

            foreach (LineNumberStrip strip in _frmMain.LineNumberStrips)
                strip.ScrollSpeed = UserSettings.Instance.LineNumScrollSpeed;
        }

        #endregion

        private void btnRestore_Click(object sender, EventArgs e)
        {
            // Reset everything except for culture and bootCount
            string culture = UserSettings.Instance.Culture;
            int bootCount = UserSettings.Instance.BootCount;

            UserSettings.Instance.Reset();
            UserSettings.Instance.Culture = culture;
            UserSettings.Instance.BootCount = bootCount;
            RecentFileQue.Initialize();

            this.SuspendLayout();
            _frmMain.LoadLastSettings();

            foreach (PlainTextBox box in _frmMain.PlainTextBoxes)
            {
                box.ShowSelectionMargin = UserSettings.Instance.ShowSelectionMargin;
                box.Font = UserSettings.Instance.Font;
                box.ForeColor = UserSettings.Instance.FontColor;
                box.BackColor = UserSettings.Instance.BackColor;
            }

            foreach (LineNumberStrip strip in _frmMain.LineNumberStrips)
            {
                strip.OffsetColor = UserSettings.Instance.LineNumStyleColor;
                strip.BoxedLineColor = UserSettings.Instance.LineNumStyleColor;
                strip.Style = UserSettings.Instance.LineNumStyle;
                strip.ForeColor = UserSettings.Instance.LineNumForeColor;
                strip.ScrollSpeed = UserSettings.Instance.LineNumScrollSpeed;
            }

            UserSettings.Instance.Signature = Environment.UserName;

            UpdateControlStates();
            this.ResumeLayout();
            MsgBox.Show("Settings have been restored to default", MessageBoxIcon.Asterisk);
        }

        private void btnClearRecentList_Click(object sender, EventArgs e)
        {
            RecentFileQue.ClearRecentList();
            btnClearRecentList.Enabled = false;
        }

        private void btnClose_Click(object sender, EventArgs e)
        {
            this.Close();
        }
    }
}
