/**
 * 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.
 */
package org.apache.rya.streams.querymanager;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

import org.apache.rya.streams.api.entity.StreamsQuery;
import org.apache.rya.streams.api.queries.InMemoryQueryChangeLog;
import org.apache.rya.streams.api.queries.QueryChange;
import org.apache.rya.streams.api.queries.QueryChangeLog;
import org.apache.rya.streams.querymanager.QueryManager.LogEvent;
import org.apache.rya.streams.querymanager.QueryManager.LogEventWorker;
import org.apache.rya.streams.querymanager.QueryManager.QueryEvent;
import org.junit.Test;

/**
 * Unit tests the methods of {@link LogEventWorker}.
 */
public class LogEventWorkerTest {

    @Test
    public void shutdownSignalKillsThread() {
        // The signal that will kill the working thread.
        final AtomicBoolean shutdownSignal = new AtomicBoolean(false);

        // The thread that will perform the LogEventWorker task.
        final Thread logEventWorker = new Thread(new LogEventWorker(new ArrayBlockingQueue<>(1),
                new ArrayBlockingQueue<>(1), 50, TimeUnit.MILLISECONDS, shutdownSignal));
        logEventWorker.start();

        // Wait longer than the poll time to see if the thread died. Show that it is still running.
        assertTrue(ThreadUtil.stillAlive(logEventWorker, 200));

        // Set the shutdown signal to true and join the thread. If we were able to join, then it shut down.
        shutdownSignal.set(true);
        assertFalse(ThreadUtil.stillAlive(logEventWorker, 500));
    }

    @Test
    public void nofity_logCreated_doesNotExist() throws Exception {
        // The signal that will kill the working thread.
        final AtomicBoolean shutdownSignal = new AtomicBoolean(false);

        // The queue used to feed work.
        final BlockingQueue<LogEvent> logEventQueue = new ArrayBlockingQueue<>(10);

        // The queue work is written to.
        final BlockingQueue<QueryEvent> queryEventQueue = new ArrayBlockingQueue<>(10);

        // The Query Change Log that will be watched.
        final QueryChangeLog changeLog = new InMemoryQueryChangeLog();

        // Write a message that indicates a new query should be active.
        final UUID firstQueryId = UUID.randomUUID();
        changeLog.write(QueryChange.create(firstQueryId, "select * where { ?a ?b ?c . }", true, false));

        // Write a message that adds an active query, but then makes it inactive. Because both of these
        // events are written to the log before the worker subscribes to the repository for updates, they
        // must result in a single query stopped event.
        final UUID secondQueryId = UUID.randomUUID();
        changeLog.write(QueryChange.create(secondQueryId, "select * where { ?d ?e ?f . }", true, false));
        changeLog.write(QueryChange.update(secondQueryId, false));

        // Start the worker that will be tested.
        final Thread logEventWorker = new Thread(new LogEventWorker(logEventQueue,
                queryEventQueue, 50, TimeUnit.MILLISECONDS, shutdownSignal));
        logEventWorker.start();

        try {
            // Write a unit of work that indicates a log was created.
            final LogEvent createLogEvent = LogEvent.create("rya", changeLog);
            logEventQueue.offer(createLogEvent);

            // We must see the following Query Events added to the work queue.
            // Query 1, executing.
            // Query 2, stopped.
            Set<QueryEvent> expectedEvents = new HashSet<>();
            expectedEvents.add(QueryEvent.executing("rya",
                    new StreamsQuery(firstQueryId, "select * where { ?a ?b ?c . }", true, false)));
            expectedEvents.add(QueryEvent.stopped("rya", secondQueryId));

            Set<QueryEvent> queryEvents = new HashSet<>();
            queryEvents.add( queryEventQueue.poll(500, TimeUnit.MILLISECONDS) );
            queryEvents.add( queryEventQueue.poll(500, TimeUnit.MILLISECONDS) );

            assertEquals(expectedEvents, queryEvents);

            // Write an event to the change log that stops the first query.
            changeLog.write(QueryChange.update(firstQueryId, false));

            // Show it was also reflected in the changes.
            // Query 1, stopped.
            expectedEvents = new HashSet<>();
            expectedEvents.add(QueryEvent.stopped("rya", firstQueryId));

            queryEvents = new HashSet<>();
            queryEvents.add( queryEventQueue.poll(500, TimeUnit.MILLISECONDS) );

            assertEquals(expectedEvents, queryEvents);
        } finally {
            shutdownSignal.set(true);
            logEventWorker.join();
        }
    }

    @Test
    public void nofity_logCreated_exists() throws Exception {
        // The signal that will kill the working thread.
        final AtomicBoolean shutdownSignal = new AtomicBoolean(false);

        // The queue used to feed work.
        final BlockingQueue<LogEvent> logEventQueue = new ArrayBlockingQueue<>(10);

        // The queue work is written to.
        final BlockingQueue<QueryEvent> queryEventQueue = new ArrayBlockingQueue<>(10);

        // The Query Change Log that will be watched.
        final QueryChangeLog changeLog = new InMemoryQueryChangeLog();

        // Write a message that indicates a new query should be active.
        final UUID firstQueryId = UUID.randomUUID();
        changeLog.write(QueryChange.create(firstQueryId, "select * where { ?a ?b ?c . }", true, false));

        // Start the worker that will be tested.
        final Thread logEventWorker = new Thread(new LogEventWorker(logEventQueue,
                queryEventQueue, 50, TimeUnit.MILLISECONDS, shutdownSignal));
        logEventWorker.start();

        try {
            // Write a unit of work that indicates a log was created.
            final LogEvent createLogEvent = LogEvent.create("rya", changeLog);
            logEventQueue.offer(createLogEvent);

            // Say the same log was created a second time.
            logEventQueue.offer(createLogEvent);

            // Show that only a single unit of work was added for the log. This indicates the
            // second message was effectively skipped as it would have add its work added twice otherwise.
            final Set<QueryEvent> expectedEvents = new HashSet<>();
            expectedEvents.add(QueryEvent.executing("rya",
                    new StreamsQuery(firstQueryId, "select * where { ?a ?b ?c . }", true, false)));

            final Set<QueryEvent> queryEvents = new HashSet<>();
            queryEvents.add( queryEventQueue.poll(500, TimeUnit.MILLISECONDS) );

            assertNull(queryEventQueue.poll(500, TimeUnit.MILLISECONDS));
            assertEquals(expectedEvents, queryEvents);
        } finally {
            shutdownSignal.set(true);
            logEventWorker.join();
        }
    }

    @Test
    public void notify_logDeleted_exists() throws Exception {
        // The signal that will kill the working thread.
        final AtomicBoolean shutdownSignal = new AtomicBoolean(false);

        // The queue used to feed work.
        final BlockingQueue<LogEvent> logEventQueue = new ArrayBlockingQueue<>(10);

        // The queue work is written to.
        final BlockingQueue<QueryEvent> queryEventQueue = new ArrayBlockingQueue<>(10);

        // The Query Change Log that will be watched.
        final QueryChangeLog changeLog = new InMemoryQueryChangeLog();

        // Start the worker that will be tested.
        final Thread logEventWorker = new Thread(new LogEventWorker(logEventQueue,
                queryEventQueue, 50, TimeUnit.MILLISECONDS, shutdownSignal));
        logEventWorker.start();

        try {
            // Write a unit of work that indicates a log was created.
            final LogEvent createLogEvent = LogEvent.create("rya", changeLog);
            logEventQueue.offer(createLogEvent);

            // Write a unit of work that indicates a log was deleted.
            logEventQueue.offer(LogEvent.delete("rya"));

            // Show that a single unit of work was created for deleting everything for "rya".
            assertEquals(QueryEvent.stopALL("rya"),  queryEventQueue.poll(500, TimeUnit.MILLISECONDS));
            assertNull(queryEventQueue.poll(500, TimeUnit.MILLISECONDS));
        } finally {
            shutdownSignal.set(true);
            logEventWorker.join();
        }
    }

    @Test
    public void notify_logDeleted_doesNotExist() throws Exception {
        // The signal that will kill the working thread.
        final AtomicBoolean shutdownSignal = new AtomicBoolean(false);

        // The queue used to feed work.
        final BlockingQueue<LogEvent> logEventQueue = new ArrayBlockingQueue<>(10);

        // The queue work is written to.
        final BlockingQueue<QueryEvent> queryEventQueue = new ArrayBlockingQueue<>(10);

        // Start the worker that will be tested.
        final Thread logEventWorker = new Thread(new LogEventWorker(logEventQueue,
                queryEventQueue, 50, TimeUnit.MILLISECONDS, shutdownSignal));
        logEventWorker.start();

        try {
            // Write a unit of work that indicates a log was deleted. Since it was never created,
            // this will not cause anything to be written to the QueryEvent queue.
            logEventQueue.offer(LogEvent.delete("rya"));

            // Show that a single unit of work was created for deleting everything for "rya".
            assertNull(queryEventQueue.poll(500, TimeUnit.MILLISECONDS));
        } finally {
            shutdownSignal.set(true);
            logEventWorker.join();
        }
    }
}