using J2N.Threading.Atomic;
using Lucene.Net.Attributes;
using Lucene.Net.Diagnostics;
using Lucene.Net.Documents;
using Lucene.Net.Index;
using Lucene.Net.Store;
using Lucene.Net.Util;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Threading;
using Console = Lucene.Net.Util.SystemConsole;
using Directory = Lucene.Net.Store.Directory;

namespace Lucene.Net.Replicator
{
    /*
     * 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.
     */

    [TestFixture]
    public class IndexReplicationClientTest : ReplicatorTestCase
    {
        private class IndexReadyCallback : IDisposable
        {
            private readonly Directory indexDir;
#pragma warning disable CA2213 // Disposable fields should be disposed
            private DirectoryReader reader;
#pragma warning restore CA2213 // Disposable fields should be disposed
            private long lastGeneration = -1;

            public IndexReadyCallback(Directory indexDir)
            {
                this.indexDir = indexDir;
                if (DirectoryReader.IndexExists(indexDir))
                {
                    reader = DirectoryReader.Open(indexDir);
                    lastGeneration = reader.IndexCommit.Generation;
                }
            }

            public bool? Call()
            {
                if (reader == null)
                {
                    reader = DirectoryReader.Open(indexDir);
                    lastGeneration = reader.IndexCommit.Generation;
                }
                else
                {
                    DirectoryReader newReader = DirectoryReader.OpenIfChanged(reader);
                    assertNotNull("should not have reached here if no changes were made to the index", newReader);
                    long newGeneration = newReader.IndexCommit.Generation;
                    assertTrue("expected newer generation; current=" + lastGeneration + " new=" + newGeneration, newGeneration > lastGeneration);
                    reader.Dispose();
                    reader = newReader;
                    lastGeneration = newGeneration;
                    TestUtil.CheckIndex(indexDir);
                }
                return null;
            }
            public void Dispose()
            {
                IOUtils.Dispose(reader);
            }
        }


        private MockDirectoryWrapper publishDir, handlerDir;
        private IReplicator replicator;
        private ISourceDirectoryFactory sourceDirFactory;
        private ReplicationClient client;
        private IReplicationHandler handler;
        private IndexWriter publishWriter;
        private IndexReadyCallback callback;

        private const string VERSION_ID = "version";

        private void AssertHandlerRevision(int expectedId, Directory dir)
        {
            // loop as long as client is alive. test-framework will terminate us if
            // there's a serious bug, e.g. client doesn't really update. otherwise,
            // introducing timeouts is not good, can easily lead to false positives.
            while (client.IsUpdateThreadAlive)
            {
                // give client a chance to update
                Thread.Sleep(100);
                try
                {
                    DirectoryReader reader = DirectoryReader.Open(dir);
                    try
                    {
                        int handlerId = int.Parse(reader.IndexCommit.UserData[VERSION_ID], NumberStyles.HexNumber);
                        if (expectedId == handlerId)
                        {
                            return;
                        }
                        else if (Verbose)
                        {
                            Console.WriteLine("expectedID=" + expectedId + " actual=" + handlerId + " generation=" + reader.IndexCommit.Generation);
                        }
                    }
                    finally
                    {
                        reader.Dispose();
                    }
                }
                catch (Exception)
                {
                    // we can hit IndexNotFoundException or e.g. EOFException (on
                    // segments_N) because it is being copied at the same time it is read by
                    // DirectoryReader.open().
                }
            }
        }

        private IRevision CreateRevision(int id)
        {
            publishWriter.AddDocument(new Document());
            publishWriter.SetCommitData(new Dictionary<string, string>{
                { VERSION_ID, id.ToString("X") }
            });
            publishWriter.Commit();
            return new IndexRevision(publishWriter);
        }

        public override void SetUp()
        {
            base.SetUp();

            publishDir = NewMockDirectory();
            handlerDir = NewMockDirectory();
            sourceDirFactory = new PerSessionDirectoryFactory(CreateTempDir("replicationClientTest").FullName);
            replicator = new LocalReplicator();
            callback = new IndexReadyCallback(handlerDir);
            handler = new IndexReplicationHandler(handlerDir, callback.Call);
            client = new ReplicationClient(replicator, handler, sourceDirFactory);

            IndexWriterConfig conf = NewIndexWriterConfig(TEST_VERSION_CURRENT, null);
            conf.IndexDeletionPolicy = new SnapshotDeletionPolicy(conf.IndexDeletionPolicy);
            publishWriter = new IndexWriter(publishDir, conf);
        }

        public override void TearDown()
        {
            IOUtils.Dispose(client, callback, publishWriter, replicator, publishDir, handlerDir);
            base.TearDown();
        }

        [Test]
        public void TestNoUpdateThread()
        {
            assertNull("no version expected at start", handler.CurrentVersion);

            // Callback validates the replicated ind
            replicator.Publish(CreateRevision(1));
            client.UpdateNow();

            replicator.Publish(CreateRevision(2));
            client.UpdateNow();

            // Publish two revisions without update,
            replicator.Publish(CreateRevision(3));
            replicator.Publish(CreateRevision(4));
            client.UpdateNow();
        }


        [Test]
        public void TestUpdateThread()
        {
            client.StartUpdateThread(10, "index");

            replicator.Publish(CreateRevision(1));
            AssertHandlerRevision(1, handlerDir);

            replicator.Publish(CreateRevision(2));
            AssertHandlerRevision(2, handlerDir);

            // Publish two revisions without update, handler should be upgraded to latest
            replicator.Publish(CreateRevision(3));
            replicator.Publish(CreateRevision(4));
            AssertHandlerRevision(4, handlerDir);
        }

        [Test]
        public void TestRestart()
        {
            replicator.Publish(CreateRevision(1));
            client.UpdateNow();

            replicator.Publish(CreateRevision(2));
            client.UpdateNow();

            client.StopUpdateThread();
            client.Dispose();
            client = new ReplicationClient(replicator, handler, sourceDirFactory);

            // Publish two revisions without update, handler should be upgraded to latest
            replicator.Publish(CreateRevision(3));
            replicator.Publish(CreateRevision(4));
            client.UpdateNow();
        }

        // This test verifies that the client and handler do not end up in a corrupt
        // index if exceptions are thrown at any point during replication. Either when
        // a client copies files from the server to the temporary space, or when the
        // handler copies them to the index directory.
        [Test]
        [Deadlock][Timeout(600000)]
        public void TestConsistencyOnExceptions()
        {
            // so the handler's index isn't empty
            replicator.Publish(CreateRevision(1));
            client.UpdateNow();
            client.Dispose();
            callback.Dispose();

            // Replicator violates write-once policy. It may be that the
            // handler copies files to the index dir, then fails to copy a
            // file and reverts the copy operation. On the next attempt, it
            // will copy the same file again. There is nothing wrong with this
            // in a real system, but it does violate write-once, and MDW
            // doesn't like it. Disabling it means that we won't catch cases
            // where the handler overwrites an existing index file, but
            // there's nothing currently we can do about it, unless we don't
            // use MDW.
            handlerDir.PreventDoubleWrite = false;

            // wrap sourceDirFactory to return a MockDirWrapper so we can simulate errors
            ISourceDirectoryFactory @in = sourceDirFactory;
            AtomicInt32 failures = new AtomicInt32(AtLeast(10));

            // wrap sourceDirFactory to return a MockDirWrapper so we can simulate errors
            sourceDirFactory = new SourceDirectoryFactoryAnonymousInnerClass(this, @in, failures);
            handler = new IndexReplicationHandler(handlerDir, () =>
            {
                if (Random.NextDouble() < 0.2 && failures > 0)
                    throw new Exception("random exception from callback");
                return null;
            });
            client = new ReplicationClientAnonymousInnerClass(this, replicator, handler, sourceDirFactory, failures);
            client.StartUpdateThread(10, "index");

            Directory baseHandlerDir = handlerDir.Delegate;
            int numRevisions = AtLeast(20);
            for (int i = 2; i < numRevisions; i++)
            {
                replicator.Publish(CreateRevision(i));
                AssertHandlerRevision(i, baseHandlerDir);
            }

            // disable errors -- maybe randomness didn't exhaust all allowed failures,
            // and we don't want e.g. CheckIndex to hit false errors. 
            handlerDir.MaxSizeInBytes = 0;
            handlerDir.RandomIOExceptionRate = 0.0;
            handlerDir.RandomIOExceptionRateOnOpen = 0.0;
        }

        private class SourceDirectoryFactoryAnonymousInnerClass : ISourceDirectoryFactory
        {
            private long clientMaxSize = 100, handlerMaxSize = 100;
            private double clientExRate = 1.0, handlerExRate = 1.0;

            private readonly IndexReplicationClientTest test;
            private readonly ISourceDirectoryFactory @in;
            private readonly AtomicInt32 failures;

            public SourceDirectoryFactoryAnonymousInnerClass(IndexReplicationClientTest test, ISourceDirectoryFactory @in, AtomicInt32 failures)
            {
                this.test = test;
                this.@in = @in;
                this.failures = failures;
            }

            public void CleanupSession(string sessionId)
            {
                @in.CleanupSession(sessionId);
            }

            public Directory GetDirectory(string sessionId, string source)
            {
                Directory dir = @in.GetDirectory(sessionId, source);
                if (Random.nextBoolean() && failures > 0)
                { // client should fail, return wrapped dir
                    MockDirectoryWrapper mdw = new MockDirectoryWrapper(Random, dir);
                    mdw.RandomIOExceptionRateOnOpen = clientExRate;
                    mdw.MaxSizeInBytes = clientMaxSize;
                    mdw.RandomIOExceptionRate = clientExRate;
                    mdw.CheckIndexOnDispose = false;
                    clientMaxSize *= 2;
                    clientExRate /= 2;
                    return mdw;
                }

                if (failures > 0 && Random.nextBoolean())
                { // handler should fail
                    test.handlerDir.MaxSizeInBytes = handlerMaxSize;
                    test.handlerDir.RandomIOExceptionRateOnOpen = handlerExRate;
                    test.handlerDir.RandomIOExceptionRate = handlerExRate;
                    handlerMaxSize *= 2;
                    handlerExRate /= 2;
                }
                else
                {
                    // disable errors
                    test.handlerDir.MaxSizeInBytes = 0;
                    test.handlerDir.RandomIOExceptionRate = 0;
                    test.handlerDir.RandomIOExceptionRateOnOpen = 0.0;
                }
                return dir;
            }
        }

        private class ReplicationClientAnonymousInnerClass : ReplicationClient
        {
            private readonly IndexReplicationClientTest test;
            private readonly AtomicInt32 failures;

            public ReplicationClientAnonymousInnerClass(IndexReplicationClientTest test, IReplicator replicator, IReplicationHandler handler, ISourceDirectoryFactory factory, AtomicInt32 failures)
                : base(replicator, handler, factory)
            {
                this.test = test;
                this.failures = failures;
            }

            protected override void HandleUpdateException(Exception exception)
            {
                if (exception is IOException)
                {
                    if (Verbose)
                    {
                        Console.WriteLine("hit exception during update: " + exception);
                    }

                    try
                    {
                        // test that the index can be read and also some basic statistics
                        DirectoryReader reader = DirectoryReader.Open(test.handlerDir.Delegate);
                        try
                        {
                            int numDocs = reader.NumDocs;
                            int version = int.Parse(reader.IndexCommit.UserData[VERSION_ID], NumberStyles.HexNumber);
                            assertEquals(numDocs, version);
                        }
                        finally
                        {
                            reader.Dispose();
                        }
                        // verify index consistency
                        TestUtil.CheckIndex(test.handlerDir.Delegate);
                    }
                    finally
                    {
                        // count-down number of failures
                        failures.DecrementAndGet();
                        if (Debugging.AssertsEnabled) Debugging.Assert(failures >= 0,"handler failed too many times: {0}", failures);
                        if (Verbose)
                        {
                            if (failures == 0)
                            {
                                Console.WriteLine("no more failures expected");
                            }
                            else
                            {
                                Console.WriteLine("num failures left: " + failures);
                            }
                        }
                    }
                }
                else
                {
                    throw exception;
                }
            }
        }

    }
}