using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml;
using ZionSchematics.Models.SearchContentTypes;
using ZionSchematics.Models.SearchModes;
using ZionVault.Basic;

namespace ZionSchematics.Models
{
    [Serializable]
    public class SearchOptions
    {
        public ISearchMode SearchMode { get; set; }
        public IContentType ContentType { get; set; }

        public Location Rect { get; set; }

        public int MaxLength { get; set; }
        public int MinLength { get; set; }

        public int MaxSpaceBetweenWords { get; set; }

        public bool IgnoreCase { get; set; }
        public bool IgnorePatternWhitespace { get; set; }
        public bool WholeWordsOnly { get; set; }

        public int MaxNumberOfLines { get; set; }
        public int MinNumberOfLines { get; set; }

        public int MaxSpaceLength { get; set; }

        public double MaxErrorsPercentage { get; set; }
        public int MaxNumberOfErrors { get; set; }

        public List<string> SearchValues { get; set; }

        public List<string> ExcludedElements { get; set; }

        public SearchOptions(ISearchMode mode, IContentType type,
            Location rect = null, int minlength = 0, int maxlength = 0, int maxspacebetweenwords = 0,
            bool ignorecase = true, bool ignorepatterwhitespace = true, bool wholewordsonly = false,
            int minnumberoflines = 0, int maxnumberoflines = 0, int maxspacelenght = 0, int maxerrorpercentage = 0,
            int maxnumberoferrors = 0, string[] searchvalues = null, List<string> excludedElements = null) : base()
        {
            this.SearchMode = mode;
            this.ContentType = type;
            this.Rect = rect;
            this.MaxLength = maxlength;
            this.MinLength = minlength;
            this.MaxSpaceBetweenWords = maxspacebetweenwords;

            this.IgnoreCase = ignorecase;
            this.IgnorePatternWhitespace = ignorepatterwhitespace;
            this.WholeWordsOnly = wholewordsonly;

            this.MaxNumberOfLines = maxnumberoflines;
            this.MinNumberOfLines = minnumberoflines;

            this.MaxSpaceLength = maxspacelenght;

            this.MaxErrorsPercentage = maxerrorpercentage;
            this.MaxNumberOfErrors = maxnumberoferrors;

            if (searchvalues != null)
                this.SearchValues = searchvalues.ToList();
            else
                this.SearchValues = new List<string>();

            this.ExcludedElements = excludedElements != null ? excludedElements : new List<string>();

        }

        public SearchOptions()
        {
            this.Rect = null;
            this.MaxLength = 0;
            this.MinLength = 0;
            this.MaxSpaceBetweenWords = 0;

            this.IgnoreCase = true;
            this.IgnorePatternWhitespace = true;
            this.WholeWordsOnly = false;

            this.MaxNumberOfLines = 0;
            this.MinNumberOfLines = 0;

            this.MaxSpaceLength = 0;

            this.MaxErrorsPercentage = 0;
            this.MaxNumberOfErrors = 0;

            this.SearchValues = new List<string>();
        }


        public XmlElement Save(XmlDocument context)
        {
            XmlElement tag = context.CreateElement(@"search-options");

            XmlElement searchMode = context.CreateElement(@"search-mode");
            XmlElement rect = context.CreateElement(@"rect");
            XmlElement contentType = context.CreateElement(@"content-type");
            XmlElement ignoreCase = context.CreateElement(@"ignore-case");
            XmlElement ignorePatternWithespace = context.CreateElement(@"ignore-pattern-whitespace");
            XmlElement wholeWordsOnly = context.CreateElement(@"whole-words-only");
            XmlElement maxLength = context.CreateElement(@"max-length");
            XmlElement minLength = context.CreateElement(@"min-length");

            XmlElement maxNumberOfLines = context.CreateElement(@"max-number-of-lines");
            XmlElement minNumberOfLines = context.CreateElement(@"min-number-of-lines");
            XmlElement maxSpaceBetweenWords = context.CreateElement(@"max-space-between-words");
            XmlElement maxNumberOfErrors = context.CreateElement(@"max-number-of-errors");
            XmlElement maxPercentageOfErrors = context.CreateElement(@"max-percentage-of-errors");

            XmlElement searchValues = context.CreateElement(@"search-values");
            XmlElement excludeElements = context.CreateElement(@"excluded-elements");

            searchMode.InnerText = this.SearchMode.Mode;
            if (this.Rect == null)
                rect.InnerText = string.Empty;
            else
                rect.InnerText = this.Rect.ToString();
            contentType.InnerText = this.ContentType.Type;
            ignoreCase.InnerText = this.IgnoreCase.ToString();
            ignorePatternWithespace.InnerText = this.IgnorePatternWhitespace.ToString();
            wholeWordsOnly.InnerText = this.WholeWordsOnly.ToString();

            maxLength.InnerText = this.MaxLength.ToString();
            minLength.InnerText = this.MinLength.ToString();
            maxNumberOfLines.InnerText = this.MaxNumberOfLines.ToString();
            minNumberOfLines.InnerText = this.MinNumberOfLines.ToString();
            maxSpaceBetweenWords.InnerText = this.MaxSpaceBetweenWords.ToString();
            maxNumberOfErrors.InnerText = this.MaxNumberOfErrors.ToString();
            maxPercentageOfErrors.InnerText = this.MaxErrorsPercentage.ToString();

            foreach (string value in this.SearchValues)
            {
                XmlElement searchValue = context.CreateElement(@"value");
                searchValue.InnerText = value;
                searchValues.AppendChild(searchValue);
            }

            this.ExcludedElements.ForEach(element =>
            {
                XmlElement excludeElement = context.CreateElement(@"element");
                excludeElement.InnerText = element;
                excludeElements.AppendChild(excludeElement);
            });

            tag.AppendChild(searchMode);
            tag.AppendChild(rect);
            tag.AppendChild(contentType);
            tag.AppendChild(ignoreCase);
            tag.AppendChild(ignorePatternWithespace);
            tag.AppendChild(wholeWordsOnly);
            tag.AppendChild(maxLength);
            tag.AppendChild(minLength);
            tag.AppendChild(maxNumberOfLines);
            tag.AppendChild(minNumberOfLines);
            tag.AppendChild(maxSpaceBetweenWords);
            tag.AppendChild(maxNumberOfErrors);
            tag.AppendChild(maxPercentageOfErrors);
            tag.AppendChild(searchValues);
            tag.AppendChild(excludeElements);

            return tag;
        }
    }
}
