﻿using Lucene.Net.Support;
using NUnit.Framework;
using Assert = Lucene.Net.TestFramework.Assert;

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 MockAnalyzer = Lucene.Net.Analysis.MockAnalyzer;
    using Document = Lucene.Net.Documents.Document;
    using DirectoryTaxonomyReader = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyReader;
    using DirectoryTaxonomyWriter = Lucene.Net.Facet.Taxonomy.Directory.DirectoryTaxonomyWriter;
    using DirectoryReader = Lucene.Net.Index.DirectoryReader;
    using IndexWriter = Lucene.Net.Index.IndexWriter;
    using IndexSearcher = Lucene.Net.Search.IndexSearcher;
    using MatchAllDocsQuery = Lucene.Net.Search.MatchAllDocsQuery;
    using Directory = Lucene.Net.Store.Directory;
    using IOUtils = Lucene.Net.Util.IOUtils;
    using TestUtil = Lucene.Net.Util.TestUtil;

    public class TestFacetsConfig : FacetTestCase
    {

        [Test]
        public virtual void TestPathToStringAndBack()
        {
            int iters = AtLeast(1000);
            for (int i = 0; i < iters; i++)
            {
                int numParts = TestUtil.NextInt32(Random, 1, 6);
                string[] parts = new string[numParts];
                for (int j = 0; j < numParts; j++)
                {
                    string s;
                    while (true)
                    {
                        s = TestUtil.RandomUnicodeString(Random);
                        if (s.Length > 0)
                        {
                            break;
                        }
                    }
                    parts[j] = s;
                }

                string s1 = FacetsConfig.PathToString(parts);
                string[] parts2 = FacetsConfig.StringToPath(s1);
                Assert.True(Arrays.Equals(parts, parts2));
            }
        }

        [Test]
        public virtual void TestAddSameDocTwice()
        {
            // LUCENE-5367: this was a problem with the previous code, making sure it
            // works with the new code.
            Directory indexDir = NewDirectory(), taxoDir = NewDirectory();
            IndexWriter indexWriter = new IndexWriter(indexDir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random)));
            DirectoryTaxonomyWriter taxoWriter = new DirectoryTaxonomyWriter(taxoDir);
            FacetsConfig facetsConfig = new FacetsConfig();
            Document doc = new Document();
            doc.Add(new FacetField("a", "b"));
            doc = facetsConfig.Build(taxoWriter, doc);
            // these two addDocument() used to fail
            indexWriter.AddDocument(doc);
            indexWriter.AddDocument(doc);
            IOUtils.Dispose(indexWriter, taxoWriter);

            DirectoryReader indexReader = DirectoryReader.Open(indexDir);
            DirectoryTaxonomyReader taxoReader = new DirectoryTaxonomyReader(taxoDir);
            IndexSearcher searcher = NewSearcher(indexReader);
            FacetsCollector fc = new FacetsCollector();
            searcher.Search(new MatchAllDocsQuery(), fc);

            Facets facets = GetTaxonomyFacetCounts(taxoReader, facetsConfig, fc);
            FacetResult res = facets.GetTopChildren(10, "a");
            Assert.AreEqual(1, res.LabelValues.Length);
            Assert.AreEqual(2, res.LabelValues[0].Value);
            IOUtils.Dispose(indexReader, taxoReader);

            IOUtils.Dispose(indexDir, taxoDir);
        }

        /// <summary>
        /// LUCENE-5479 
        /// </summary>
        [Test]
        public virtual void TestCustomDefault()
        {
            FacetsConfig config = new FacetsConfigAnonymousInnerClassHelper(this);

            Assert.True(config.GetDimConfig("foobar").IsHierarchical);
        }

        private class FacetsConfigAnonymousInnerClassHelper : FacetsConfig
        {
            private readonly TestFacetsConfig outerInstance;

            public FacetsConfigAnonymousInnerClassHelper(TestFacetsConfig outerInstance)
            {
                this.outerInstance = outerInstance;
            }

            protected override DimConfig DefaultDimConfig
            {
                get
                {
                    DimConfig config = new DimConfig();
                    config.IsHierarchical = true;
                    return config;
                }
            }
        }
    }

}