﻿using Lucene.Net.Diagnostics;
using Lucene.Net.Support;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using JCG = J2N.Collections.Generic;

namespace Lucene.Net.Facet
{
    /*
     * Licensed to the Apache Software Foundation (ASF) under one or more
     * contributor license agreements.  See the NOTICE file distributed with
     * this work for additional information regarding copyright ownership.
     * The ASF licenses this file to You under the Apache License, Version 2.0
     * (the "License"); you may not use this file except in compliance with
     * the License.  You may obtain a copy of the License at
     *
     *     http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */

    using ArrayUtil = Lucene.Net.Util.ArrayUtil;
    using AssociationFacetField = Lucene.Net.Facet.Taxonomy.AssociationFacetField;
    using BinaryDocValuesField = Lucene.Net.Documents.BinaryDocValuesField;
    using BytesRef = Lucene.Net.Util.BytesRef;
    using Document = Lucene.Net.Documents.Document;
    using FacetLabel = Lucene.Net.Facet.Taxonomy.FacetLabel;
    using Field = Lucene.Net.Documents.Field;
    using IIndexableField = Lucene.Net.Index.IIndexableField;
    using IIndexableFieldType = Lucene.Net.Index.IIndexableFieldType;
    using Int32AssociationFacetField = Lucene.Net.Facet.Taxonomy.Int32AssociationFacetField;
    using Int32sRef = Lucene.Net.Util.Int32sRef;
    using ITaxonomyWriter = Lucene.Net.Facet.Taxonomy.ITaxonomyWriter;
    using SingleAssociationFacetField = Lucene.Net.Facet.Taxonomy.SingleAssociationFacetField;
    using SortedSetDocValuesFacetField = Lucene.Net.Facet.SortedSet.SortedSetDocValuesFacetField;
    using SortedSetDocValuesField = Lucene.Net.Documents.SortedSetDocValuesField;
    using StringField = Lucene.Net.Documents.StringField;

    /// <summary>
    /// Records per-dimension configuration.  By default a
    /// dimension is flat, single valued and does
    /// not require count for the dimension; use
    /// the setters in this class to change these settings for
    /// each dim.
    /// 
    /// <para>
    /// <b>NOTE</b>: this configuration is not saved into the
    /// index, but it's vital, and up to the application to
    /// ensure, that at search time the provided <see cref="FacetsConfig"/>
    /// matches what was used during indexing.
    /// 
    ///  @lucene.experimental 
    /// </para>
    /// </summary>
    public class FacetsConfig
    {
        /// <summary>
        /// Which Lucene field holds the drill-downs and ords (as
        /// doc values). 
        /// </summary>
        public const string DEFAULT_INDEX_FIELD_NAME = "$facets";

        private readonly IDictionary<string, DimConfig> fieldTypes = new ConcurrentDictionary<string, DimConfig>();

        // Used only for best-effort detection of app mixing
        // int/float/bytes in a single indexed field:
        private readonly IDictionary<string, string> assocDimTypes = new ConcurrentDictionary<string, string>();

        private readonly object syncLock = new object(); // LUCENENET specific - avoid lock(this)

        /// <summary>
        /// Holds the configuration for one dimension
        /// 
        /// @lucene.experimental 
        /// </summary>
        public sealed class DimConfig
        {
            /// <summary>
            /// True if this dimension is hierarchical. </summary>
            public bool IsHierarchical { get; set; }

            /// <summary>
            /// True if this dimension is multi-valued. </summary>
            public bool IsMultiValued { get; set; }

            /// <summary>
            /// True if the count/aggregate for the entire dimension
            ///  is required, which is unusual (default is false). 
            /// </summary>
            public bool RequireDimCount { get; set; }

            /// <summary>
            /// Actual field where this dimension's facet labels
            ///  should be indexed 
            /// </summary>
            public string IndexFieldName { get; set; }

            /// <summary>
            /// Default constructor.
            /// </summary>
            public DimConfig()
            {
                IndexFieldName = DEFAULT_INDEX_FIELD_NAME;
            }
        }

        /// <summary>
        /// Default per-dimension configuration. </summary>
        public static readonly DimConfig DEFAULT_DIM_CONFIG = new DimConfig();

        /// <summary>
        /// Default constructor.
        /// </summary>
        public FacetsConfig()
        {
        }

        /// <summary>
        /// Get the default configuration for new dimensions.  Useful when
        /// the dimension is not known beforehand and may need different 
        /// global default settings, like <c>multivalue = true</c>.
        /// </summary>
        /// <returns>
        /// The default configuration to be used for dimensions that 
        /// are not yet set in the <see cref="FacetsConfig"/>
        /// </returns>
        protected virtual DimConfig DefaultDimConfig => DEFAULT_DIM_CONFIG;

        /// <summary>
        /// Get the current configuration for a dimension.
        /// </summary>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public virtual DimConfig GetDimConfig(string dimName)
        {
            lock (syncLock)
            {
                if (!fieldTypes.TryGetValue(dimName, out DimConfig ft))
                {
                    ft = DefaultDimConfig;
                }
                return ft;
            }
        }

        /// <summary>
        /// Pass <c>true</c> if this dimension is hierarchical
        /// (has depth > 1 paths). 
        /// </summary>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public virtual void SetHierarchical(string dimName, bool v)
        {
            lock (syncLock)
            {
                // LUCENENET: Eliminated extra lookup by using TryGetValue instead of ContainsKey
                if (!fieldTypes.TryGetValue(dimName, out DimConfig fieldType))
                {
                    fieldTypes[dimName] = new DimConfig { IsHierarchical = v };
                }
                else
                {
                    fieldType.IsHierarchical = v;
                }
            }
        }

        /// <summary>
        /// Pass <c>true</c> if this dimension may have more than
        /// one value per document. 
        /// </summary>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public virtual void SetMultiValued(string dimName, bool v)
        {
            lock (syncLock)
            {
                // LUCENENET: Eliminated extra lookup by using TryGetValue instead of ContainsKey
                if (!fieldTypes.TryGetValue(dimName, out DimConfig fieldType))
                {
                    fieldTypes[dimName] = new DimConfig { IsMultiValued = v };
                }
                else
                {
                    fieldType.IsMultiValued = v;
                }
            }
        }

        /// <summary>
        /// Pass <c>true</c> if at search time you require
        /// accurate counts of the dimension, i.e. how many
        /// hits have this dimension. 
        /// </summary>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public virtual void SetRequireDimCount(string dimName, bool v)
        {
            lock (syncLock)
            {
                // LUCENENET: Eliminated extra lookup by using TryGetValue instead of ContainsKey
                if (!fieldTypes.TryGetValue(dimName, out DimConfig fieldType))
                {
                    fieldTypes[dimName] = new DimConfig { RequireDimCount = v };
                }
                else
                {
                    fieldType.RequireDimCount = v;
                }
            }
        }

        /// <summary>
        /// Specify which index field name should hold the
        /// ordinals for this dimension; this is only used by the
        /// taxonomy based facet methods. 
        /// </summary>
        public virtual void SetIndexFieldName(string dimName, string indexFieldName)
        {
            lock (syncLock)
            {
                // LUCENENET: Eliminated extra lookup by using TryGetValue instead of ContainsKey
                if (!fieldTypes.TryGetValue(dimName, out DimConfig fieldType))
                {
                    fieldTypes[dimName] = new DimConfig { IndexFieldName = indexFieldName };
                }
                else
                {
                    fieldType.IndexFieldName = indexFieldName;
                }
            }
        }

        /// <summary>
        /// Returns map of field name to <see cref="DimConfig"/>.
        /// </summary>
        public virtual IDictionary<string, DimConfig> DimConfigs => fieldTypes;

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        private static void CheckSeen(ISet<string> seenDims, string dim)
        {
            if (seenDims.Contains(dim))
            {
                throw new ArgumentException("dimension \"" + dim + "\" is not multiValued, but it appears more than once in this document");
            }
            seenDims.Add(dim);
        }

        /// <summary>
        /// Translates any added <see cref="FacetField"/>s into normal fields for indexing;
        /// only use this version if you did not add any taxonomy-based fields 
        /// (<see cref="FacetField"/> or <see cref="AssociationFacetField"/>).
        /// 
        /// <para>
        /// <b>NOTE:</b> you should add the returned document to <see cref="Index.IndexWriter"/>, not the
        /// input one!
        /// </para>
        /// </summary>
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public virtual Document Build(Document doc)
        {
            return Build(null, doc);
        }

        /// <summary>
        /// Translates any added <see cref="FacetField"/>s into normal fields for indexing.
        /// 
        /// <para>
        /// <b>NOTE:</b> you should add the returned document to <see cref="Index.IndexWriter"/>, not the
        /// input one!
        /// </para>
        /// </summary>
        public virtual Document Build(ITaxonomyWriter taxoWriter, Document doc)
        {
            // Find all FacetFields, collated by the actual field:
            IDictionary<string, IList<FacetField>> byField = new Dictionary<string, IList<FacetField>>();

            // ... and also all SortedSetDocValuesFacetFields:
            IDictionary<string, IList<SortedSetDocValuesFacetField>> dvByField = new Dictionary<string, IList<SortedSetDocValuesFacetField>>();

            // ... and also all AssociationFacetFields
            IDictionary<string, IList<AssociationFacetField>> assocByField = new Dictionary<string, IList<AssociationFacetField>>();

            var seenDims = new JCG.HashSet<string>();

            foreach (IIndexableField field in doc.Fields)
            {
                if (field.IndexableFieldType == FacetField.TYPE)
                {
                    FacetField facetField = (FacetField)field;
                    FacetsConfig.DimConfig dimConfig = GetDimConfig(facetField.Dim);
                    if (dimConfig.IsMultiValued == false)
                    {
                        CheckSeen(seenDims, facetField.Dim);
                    }
                    string indexFieldName = dimConfig.IndexFieldName;
                    if (!byField.TryGetValue(indexFieldName, out IList<FacetField> fields))
                    {
                        fields = new List<FacetField>();
                        byField[indexFieldName] = fields;
                    }
                    fields.Add(facetField);
                }

                if (field.IndexableFieldType == SortedSetDocValuesFacetField.TYPE)
                {
                    var facetField = (SortedSetDocValuesFacetField)field;
                    FacetsConfig.DimConfig dimConfig = GetDimConfig(facetField.Dim);
                    if (dimConfig.IsMultiValued == false)
                    {
                        CheckSeen(seenDims, facetField.Dim);
                    }
                    string indexFieldName = dimConfig.IndexFieldName;
                    if (!dvByField.TryGetValue(indexFieldName, out IList<SortedSetDocValuesFacetField> fields))
                    {
                        fields = new List<SortedSetDocValuesFacetField>();
                        dvByField[indexFieldName] = fields;
                    }
                    fields.Add(facetField);
                }

                if (field.IndexableFieldType == AssociationFacetField.TYPE)
                {
                    AssociationFacetField facetField = (AssociationFacetField)field;
                    FacetsConfig.DimConfig dimConfig = GetDimConfig(facetField.Dim);
                    if (dimConfig.IsMultiValued == false)
                    {
                        CheckSeen(seenDims, facetField.Dim);
                    }
                    if (dimConfig.IsHierarchical)
                    {
                        throw new ArgumentException("AssociationFacetField cannot be hierarchical (dim=\"" + facetField.Dim + "\")");
                    }
                    if (dimConfig.RequireDimCount)
                    {
                        throw new ArgumentException("AssociationFacetField cannot requireDimCount (dim=\"" + facetField.Dim + "\")");
                    }

                    string indexFieldName = dimConfig.IndexFieldName;
                    if (!assocByField.TryGetValue(indexFieldName, out IList<AssociationFacetField> fields))
                    {
                        fields = new List<AssociationFacetField>();
                        assocByField[indexFieldName] = fields;
                    }
                    fields.Add(facetField);

                    // Best effort: detect mis-matched types in same
                    // indexed field:
                    string type;
                    if (facetField is Int32AssociationFacetField)
                    {
                        type = "int";
                    }
                    else if (facetField is SingleAssociationFacetField)
                    {
                        type = "float";
                    }
                    else
                    {
                        type = "bytes";
                    }
                    // NOTE: not thread safe, but this is just best effort:
                    if (!assocDimTypes.TryGetValue(indexFieldName, out string curType))
                    {
                        assocDimTypes[indexFieldName] = type;
                    }
                    else if (!curType.Equals(type, StringComparison.Ordinal))
                    {
                        throw new ArgumentException("mixing incompatible types of AssocationFacetField (" + curType + " and " + type + ") in indexed field \"" + indexFieldName + "\"; use FacetsConfig to change the indexFieldName for each dimension");
                    }
                }
            }

            Document result = new Document();

            ProcessFacetFields(taxoWriter, byField, result);
            ProcessSSDVFacetFields(dvByField, result);
            ProcessAssocFacetFields(taxoWriter, assocByField, result);

            //System.out.println("add stored: " + addedStoredFields);

            foreach (IIndexableField field in doc.Fields)
            {
                IIndexableFieldType ft = field.IndexableFieldType;
                if (ft != FacetField.TYPE && ft != SortedSetDocValuesFacetField.TYPE && ft != AssociationFacetField.TYPE)
                {
                    result.Add(field);
                }
            }

            return result;
        }

        private void ProcessFacetFields(ITaxonomyWriter taxoWriter, IDictionary<string, IList<FacetField>> byField, Document doc)
        {

            foreach (KeyValuePair<string, IList<FacetField>> ent in byField)
            {

                string indexFieldName = ent.Key;
                //System.out.println("  indexFieldName=" + indexFieldName + " fields=" + ent.getValue());

                Int32sRef ordinals = new Int32sRef(32);
                foreach (FacetField facetField in ent.Value)
                {

                    FacetsConfig.DimConfig ft = GetDimConfig(facetField.Dim);
                    if (facetField.Path.Length > 1 && ft.IsHierarchical == false)
                    {
                        throw new ArgumentException("dimension \"" + facetField.Dim + "\" is not hierarchical yet has " + facetField.Path.Length + " components");
                    }

                    FacetLabel cp = new FacetLabel(facetField.Dim, facetField.Path);

                    CheckTaxoWriter(taxoWriter);
                    int ordinal = taxoWriter.AddCategory(cp);
                    if (ordinals.Length == ordinals.Int32s.Length)
                    {
                        ordinals.Grow(ordinals.Length + 1);
                    }
                    ordinals.Int32s[ordinals.Length++] = ordinal;
                    //System.out.println("ords[" + (ordinals.length-1) + "]=" + ordinal);
                    //System.out.println("  add cp=" + cp);

                    if (ft.IsMultiValued && (ft.IsHierarchical || ft.RequireDimCount))
                    {
                        //System.out.println("  add parents");
                        // Add all parents too:
                        int parent = taxoWriter.GetParent(ordinal);
                        while (parent > 0)
                        {
                            if (ordinals.Int32s.Length == ordinals.Length)
                            {
                                ordinals.Grow(ordinals.Length + 1);
                            }
                            ordinals.Int32s[ordinals.Length++] = parent;
                            parent = taxoWriter.GetParent(parent);
                        }

                        if (ft.RequireDimCount == false)
                        {
                            // Remove last (dimension) ord:
                            ordinals.Length--;
                        }
                    }

                    // Drill down:
                    for (int i = 1; i <= cp.Length; i++)
                    {
                        doc.Add(new StringField(indexFieldName, PathToString(cp.Components, i), Field.Store.NO));
                    }
                }

                // Facet counts:
                // DocValues are considered stored fields:
                doc.Add(new BinaryDocValuesField(indexFieldName, DedupAndEncode(ordinals)));
            }
        }

        private void ProcessSSDVFacetFields(IDictionary<string, IList<SortedSetDocValuesFacetField>> byField, Document doc)
        {
            //System.out.println("process SSDV: " + byField);
            foreach (KeyValuePair<string, IList<SortedSetDocValuesFacetField>> ent in byField)
            {

                string indexFieldName = ent.Key;
                //System.out.println("  field=" + indexFieldName);

                foreach (SortedSetDocValuesFacetField facetField in ent.Value)
                {
                    FacetLabel cp = new FacetLabel(facetField.Dim, facetField.Label);
                    string fullPath = PathToString(cp.Components, cp.Length);
                    //System.out.println("add " + fullPath);

                    // For facet counts:
                    doc.Add(new SortedSetDocValuesField(indexFieldName, new BytesRef(fullPath)));

                    // For drill-down:
                    doc.Add(new StringField(indexFieldName, fullPath, Field.Store.NO));
                    doc.Add(new StringField(indexFieldName, facetField.Dim, Field.Store.NO));
                }
            }
        }

        private void ProcessAssocFacetFields(ITaxonomyWriter taxoWriter, IDictionary<string, IList<AssociationFacetField>> byField, Document doc)
        {
            foreach (KeyValuePair<string, IList<AssociationFacetField>> ent in byField)
            {
                byte[] bytes = new byte[16];
                int upto = 0;
                string indexFieldName = ent.Key;
                foreach (AssociationFacetField field in ent.Value)
                {
                    // NOTE: we don't add parents for associations
                    CheckTaxoWriter(taxoWriter);
                    FacetLabel label = new FacetLabel(field.Dim, field.Path);
                    int ordinal = taxoWriter.AddCategory(label);
                    if (upto + 4 > bytes.Length)
                    {
                        bytes = ArrayUtil.Grow(bytes, upto + 4);
                    }
                    // big-endian:
                    bytes[upto++] = (byte)(ordinal >> 24);
                    bytes[upto++] = (byte)(ordinal >> 16);
                    bytes[upto++] = (byte)(ordinal >> 8);
                    bytes[upto++] = (byte)ordinal;
                    if (upto + field.Assoc.Length > bytes.Length)
                    {
                        bytes = ArrayUtil.Grow(bytes, upto + field.Assoc.Length);
                    }
                    Array.Copy(field.Assoc.Bytes, field.Assoc.Offset, bytes, upto, field.Assoc.Length);
                    upto += field.Assoc.Length;

                    // Drill down:
                    for (int i = 1; i <= label.Length; i++)
                    {
                        doc.Add(new StringField(indexFieldName, PathToString(label.Components, i), Field.Store.NO));
                    }
                }
                doc.Add(new BinaryDocValuesField(indexFieldName, new BytesRef(bytes, 0, upto)));
            }
        }

        /// <summary>
        /// Encodes ordinals into a <see cref="BytesRef"/>; expert: subclass can
        /// override this to change encoding. 
        /// </summary>
        protected virtual BytesRef DedupAndEncode(Int32sRef ordinals)
        {
            Array.Sort(ordinals.Int32s, ordinals.Offset, ordinals.Length);
            byte[] bytes = new byte[5 * ordinals.Length];
            int lastOrd = -1;
            int upto = 0;
            for (int i = 0; i < ordinals.Length; i++)
            {
                int ord = ordinals.Int32s[ordinals.Offset + i];
                // ord could be == lastOrd, so we must dedup:
                if (ord > lastOrd)
                {
                    int delta;
                    if (lastOrd == -1)
                    {
                        delta = ord;
                    }
                    else
                    {
                        delta = ord - lastOrd;
                    }
                    if ((delta & ~0x7F) == 0)
                    {
                        bytes[upto] = (byte)delta;
                        upto++;
                    }
                    else if ((delta & ~0x3FFF) == 0)
                    {
                        bytes[upto] = unchecked((byte)(0x80 | ((delta & 0x3F80) >> 7)));
                        bytes[upto + 1] = (byte)(delta & 0x7F);
                        upto += 2;
                    }
                    else if ((delta & ~0x1FFFFF) == 0)
                    {
                        bytes[upto] = unchecked((byte)(0x80 | ((delta & 0x1FC000) >> 14)));
                        bytes[upto + 1] = unchecked((byte)(0x80 | ((delta & 0x3F80) >> 7)));
                        bytes[upto + 2] = (byte)(delta & 0x7F);
                        upto += 3;
                    }
                    else if ((delta & ~0xFFFFFFF) == 0)
                    {
                        bytes[upto] = unchecked((byte)(0x80 | ((delta & 0xFE00000) >> 21)));
                        bytes[upto + 1] = unchecked((byte)(0x80 | ((delta & 0x1FC000) >> 14)));
                        bytes[upto + 2] = unchecked((byte)(0x80 | ((delta & 0x3F80) >> 7)));
                        bytes[upto + 3] = (byte)(delta & 0x7F);
                        upto += 4;
                    }
                    else
                    {
                        bytes[upto] = unchecked((byte)(0x80 | ((delta & 0xF0000000) >> 28)));
                        bytes[upto + 1] = unchecked((byte)(0x80 | ((delta & 0xFE00000) >> 21)));
                        bytes[upto + 2] = unchecked((byte)(0x80 | ((delta & 0x1FC000) >> 14)));
                        bytes[upto + 3] = unchecked((byte)(0x80 | ((delta & 0x3F80) >> 7)));
                        bytes[upto + 4] = (byte)(delta & 0x7F);
                        upto += 5;
                    }
                    lastOrd = ord;
                }
            }

            return new BytesRef(bytes, 0, upto);
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        private static void CheckTaxoWriter(ITaxonomyWriter taxoWriter) // LUCENENET: CA1822: Mark members as static
        {
            if (taxoWriter == null)
            {
                throw new ThreadStateException("a non-null ITaxonomyWriter must be provided when indexing FacetField or AssociationFacetField");
            }
        }

        // Joins the path components together:
        private const char DELIM_CHAR = '\u001F';

        // Escapes any occurrence of the path component inside the label:
        private const char ESCAPE_CHAR = '\u001E';

        /// <summary>
        /// Turns a dim + path into an encoded string.
        /// </summary>
        public static string PathToString(string dim, string[] path)
        {
            string[] fullPath = new string[1 + path.Length];
            fullPath[0] = dim;
            Array.Copy(path, 0, fullPath, 1, path.Length);
            return PathToString(fullPath, fullPath.Length);
        }

        /// <summary>
        /// Turns a dim + path into an encoded string.
        /// </summary>
        public static string PathToString(string[] path)
        {
            return PathToString(path, path.Length);
        }

        /// <summary>
        /// Turns the first <paramref name="length"/> elements of <paramref name="path"/>
        /// into an encoded string. 
        /// </summary>
        public static string PathToString(string[] path, int length)
        {
            if (length == 0)
            {
                return "";
            }
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < length; i++)
            {
                string s = path[i];
                if (s.Length == 0)
                {
                    throw new ArgumentException("each path component must have length > 0 (got: \"\")");
                }
                int numChars = s.Length;
                for (int j = 0; j < numChars; j++)
                {
                    char ch = s[j];
                    if (ch == DELIM_CHAR || ch == ESCAPE_CHAR)
                    {
                        sb.Append(ESCAPE_CHAR);
                    }
                    sb.Append(ch);
                }
                sb.Append(DELIM_CHAR);
            }

            // Trim off last DELIM_CHAR:
            sb.Length -= 1;
            return sb.ToString();
        }

        /// <summary>
        /// Turns an encoded string (from a previous call to <see cref="PathToString(string[])"/>) 
        /// back into the original <see cref="T:string[]"/>. 
        /// </summary>
        public static string[] StringToPath(string s)
        {
            List<string> parts = new List<string>();
            int length = s.Length;
            if (length == 0)
            {
                return Arrays.Empty<string>();
            }
            char[] buffer = new char[length];

            int upto = 0;
            bool lastEscape = false;
            for (int i = 0; i < length; i++)
            {
                char ch = s[i];
                if (lastEscape)
                {
                    buffer[upto++] = ch;
                    lastEscape = false;
                }
                else if (ch == ESCAPE_CHAR)
                {
                    lastEscape = true;
                }
                else if (ch == DELIM_CHAR)
                {
                    parts.Add(new string(buffer, 0, upto));
                    upto = 0;
                }
                else
                {
                    buffer[upto++] = ch;
                }
            }
            parts.Add(new string(buffer, 0, upto));
            if (Debugging.AssertsEnabled) Debugging.Assert(!lastEscape);
            return parts.ToArray();
        }
    }
}