using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using FooEditEngine;
using FooEditEngine.Metro;

namespace FooEditor
{
    class FindFlyoutViewModel : ViewModelBase
    {
        static Color foundMarkerColor = new Color(64, 128, 128, 128);
        FooTextBox textBox;
        IEnumerator<SearchResult> iterator;
        bool canReplaceNext = false;
        string currentPatter;
        public FindFlyoutViewModel(FooTextBox textbox)
        {
            this.textBox = textbox;
        }

        public const int FoundMarkerID = 2;

        string _FindPattern;
        public string FindPattern
        {
            get
            {
                return this._FindPattern;
            }
            set
            {
                this._FindPattern = value;
                this.OnPropertyChanged();
            }
        }

        string _ReplacePattern;
        public string ReplacePattern
        {
            get
            {
                return this._ReplacePattern;
            }
            set
            {
                this._ReplacePattern = value;
                this.OnPropertyChanged();
            }
        }

        bool _UseRegEx;
        public bool UseRegEx
        {
            get
            {
                return this._UseRegEx;
            }
            set
            {
                this._UseRegEx = value;
                this.Reset();
                this.OnPropertyChanged();
            }
        }

        bool _RestrictSearch;
        public bool RestrictSearch
        {
            get
            {
                return this._RestrictSearch;
            }
            set
            {
                this._RestrictSearch = value;
                this.Reset();
                this.OnPropertyChanged();
            }
        }

        bool _UseGroup;
        public bool UseGroup
        {
            get
            {
                return this._UseGroup;
            }
            set
            {
                this._UseGroup = value;
                this.OnPropertyChanged();
            }
        }

        string _Result;
        public string Result
        {
            get
            {
                return this._Result;
            }
            set
            {
                this._Result = value;
                this.OnPropertyChanged();
            }
        }

        public DelegateCommand<object> FindNextCommand
        {
            get
            {
                return new DelegateCommand<object>((s) =>
                {
                    this.Result = string.Empty;
                    try
                    {
                        RegexOptions opt = this.RestrictSearch ? RegexOptions.None : RegexOptions.IgnoreCase;
                        this.FindNext(this.FindPattern, this.UseRegEx, opt);
                    }
                    catch (Exception e)
                    {
                        this.Result = e.Message;
                    }
                });
            }
        }

        public DelegateCommand<object> ReplaceNextCommand
        {
            get
            {
                return new DelegateCommand<object>((s) =>
                {
                    this.Result = string.Empty;
                    try
                    {
                        this.Replace(this.ReplacePattern, this.UseGroup);
                        RegexOptions opt = this.RestrictSearch ? RegexOptions.None : RegexOptions.IgnoreCase;
                        this.FindNext(this.FindPattern, this.UseRegEx, opt);
                    }
                    catch (Exception e)
                    {
                        this.Result = e.Message;
                    }
                });
            }
        }

        public DelegateCommand<object> ReplaceAllCommand
        {
            get
            {
                return new DelegateCommand<object>((s) =>
                {
                    this.Result = string.Empty;
                    try
                    {
                        RegexOptions opt = this.RestrictSearch ? RegexOptions.None : RegexOptions.IgnoreCase;
                        this.ReplaceAll(this.FindPattern, this.ReplacePattern, this.UseGroup, this.UseRegEx, opt);
                    }
                    catch (Exception e)
                    {
                        this.Result = e.Message;
                    }
                });
            }
        }

        public void Reset()
        {
            this.iterator = null;
        }

        void FindNext(string pattern, bool useregex, RegexOptions opt)
        {
            if (this.iterator == null || this.currentPatter != pattern)
            {
                this.currentPatter = pattern;
                this.textBox.Document.SetFindParam(pattern, useregex, opt);
                if (AppSettings.Current.ShowFoundPattern)
                {
                    this.textBox.MarkerPatternSet.Add(FoundMarkerID, this.textBox.Document.CreateWatchDogByFindParam(HilightType.Select, foundMarkerColor));
                }
                this.iterator = this.textBox.Document.Find();
            }
            if (!this.iterator.MoveNext())
            {
                this.canReplaceNext = false;
                var loader = new Windows.ApplicationModel.Resources.ResourceLoader();
                throw new Exception(loader.GetString("NotFoundInDocument"));
            }
            SearchResult sr = this.iterator.Current;
            this.textBox.JumpCaret(sr.End);
            this.textBox.Select(sr.Start, sr.End - sr.Start + 1);
            this.textBox.Refresh();
            this.canReplaceNext = true;
            return;
        }

        void Replace(string newpattern, bool usegroup)
        {
            if (!this.canReplaceNext)
                return;
            SearchResult sr = this.iterator.Current;
            if (usegroup)
                this.textBox.SelectedText = sr.Result(newpattern);
            else
                this.textBox.SelectedText = newpattern;
            this.textBox.Refresh();
        }

        void ReplaceAll(string pattern, string newpattern, bool usegroup, bool useregex, RegexOptions opt)
        {
            this.textBox.Document.FireUpdateEvent = false;
            if (useregex)
            {
                this.textBox.Document.SetFindParam(pattern, useregex, opt);
                this.textBox.Document.ReplaceAll(newpattern, usegroup);
            }
            else
            {
                this.textBox.Document.ReplaceAll2(pattern, newpattern, (opt & RegexOptions.IgnoreCase) == RegexOptions.IgnoreCase);
            }
            this.textBox.Document.FireUpdateEvent = true;
            this.textBox.Refresh();
        }
    }
}
