using Lucene.Net.Documents;
using Lucene.Net.Index.Extensions;
using NUnit.Framework;
using System.Text;

namespace Lucene.Net.Store
{
    /*
     * 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 DirectoryReader = Lucene.Net.Index.DirectoryReader;
    using Document = Documents.Document;
    using Field = Field;
    using IndexReader = Lucene.Net.Index.IndexReader;
    using IndexWriter = Lucene.Net.Index.IndexWriter;
    using IndexWriterConfig = Lucene.Net.Index.IndexWriterConfig;
    using LuceneTestCase = Lucene.Net.Util.LuceneTestCase;
    using MockAnalyzer = Lucene.Net.Analysis.MockAnalyzer;
    using OpenMode = Lucene.Net.Index.OpenMode;

    [TestFixture]
    public class TestWindowsMMap : LuceneTestCase
    {
        private const string ALPHABET = "abcdefghijklmnopqrstuvwzyz";

        [SetUp]
        public override void SetUp()
        {
            base.SetUp();
        }

        private string RandomToken()
        {
            int tl = 1 + Random.Next(7);
            StringBuilder sb = new StringBuilder();
            for (int cx = 0; cx < tl; cx++)
            {
                int c = Random.Next(25);
                sb.Append(ALPHABET.Substring(c, 1));
            }
            return sb.ToString();
        }

        private string RandomField()
        {
            int fl = 1 + Random.Next(3);
            StringBuilder fb = new StringBuilder();
            for (int fx = 0; fx < fl; fx++)
            {
                fb.Append(RandomToken());
                fb.Append(" ");
            }
            return fb.ToString();
        }

        [Test]
        public virtual void TestMmapIndex()
        {
            // sometimes the directory is not cleaned by rmDir, because on Windows it
            // may take some time until the files are finally dereferenced. So clean the
            // directory up front, or otherwise new IndexWriter will fail.
            var dirPath = CreateTempDir("testLuceneMmap");
            RmDir(dirPath.FullName);
            var dir = new MMapDirectory(dirPath, null);

            // plan to add a set of useful stopwords, consider changing some of the
            // interior filters.
            using (var analyzer = new MockAnalyzer(Random))
            {
                // TODO: something about lock timeouts and leftover locks.
                using (var writer = new IndexWriter(dir,
                    new IndexWriterConfig(TEST_VERSION_CURRENT, analyzer).SetOpenMode(
                        OpenMode.CREATE)))
                {
                    writer.Commit();
                    using (IndexReader reader = DirectoryReader.Open(dir))
                    {
                        var searcher = NewSearcher(reader);
                        var num = AtLeast(1000);
                        for (int dx = 0; dx < num; dx++)
                        {
                            var f = RandomField();
                            var doc = new Document();
                            doc.Add(NewTextField("data", f, Field.Store.YES));
                            writer.AddDocument(doc);
                        }
                    }
                }

                RmDir(dirPath.FullName);
            }
        }

        private static void RmDir(string dir)
        {
            if (!System.IO.Directory.Exists(dir))
            {
                return;
            }

            foreach (string f in System.IO.Directory.GetFiles(dir))
            {
                System.IO.File.Delete(f);
            }

            System.IO.Directory.Delete(dir);
        }
    }
}