/*
 * Copyright 2014-present Open Networking Laboratory
 *
 * Licensed 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.onosproject.net.intent.impl;

import com.google.common.collect.HashMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import org.hamcrest.Description;
import org.hamcrest.TypeSafeMatcher;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.onosproject.TestApplicationId;
import org.onosproject.cfg.ComponentConfigAdapter;
import org.onosproject.cfg.ComponentConfigService;
import org.onosproject.common.event.impl.TestEventDispatcher;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.impl.TestCoreManager;
import org.onosproject.net.NetworkResource;
import org.onosproject.net.intent.FlowRuleIntent;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentCompilationException;
import org.onosproject.net.intent.IntentCompiler;
import org.onosproject.net.intent.IntentData;
import org.onosproject.net.intent.IntentEvent;
import org.onosproject.net.intent.IntentEvent.Type;
import org.onosproject.net.intent.IntentExtensionService;
import org.onosproject.net.intent.IntentId;
import org.onosproject.net.intent.IntentListener;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.intent.IntentState;
import org.onosproject.net.intent.Key;
import org.onosproject.store.trivial.SimpleIntentStore;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

import static org.easymock.EasyMock.mock;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.*;
import static org.onlab.junit.TestTools.assertAfter;
import static org.onlab.util.Tools.delay;
import static org.onosproject.net.NetTestTools.injectEventDispatcher;
import static org.onosproject.net.intent.IntentState.*;
import static org.onosproject.net.intent.IntentTestsMocks.MockFlowRule;
import static org.onosproject.net.intent.IntentTestsMocks.MockIntent;

/**
 * Test intent manager and transitions.
 *
 * TODO implement the following tests:
 *  - {submit, withdraw, update, replace} intent
 *  - {submit, update, recompiling} intent with failed compilation
 *  - failed reservation
 *  - push timeout recovery
 *  - failed items recovery
 *
 *  in general, verify intents store, flow store, and work queue
 */

public class IntentManagerTest {

    private static final int SUBMIT_TIMEOUT_MS = 1000;
    private static final ApplicationId APPID = new TestApplicationId("manager-test");

    private IntentManager manager;
    private MockFlowRuleService flowRuleService;

    protected IntentService service;
    protected IntentExtensionService extensionService;
    protected TestListener listener = new TestListener();
    protected TestIntentCompiler compiler = new TestIntentCompiler();

    private static class TestListener implements IntentListener {
        final Multimap<IntentEvent.Type, IntentEvent> events = HashMultimap.create();
        Map<IntentEvent.Type, CountDownLatch> latchMap = Maps.newHashMap();

        @Override
        public void event(IntentEvent event) {
            events.put(event.type(), event);
            if (latchMap.containsKey(event.type())) {
                latchMap.get(event.type()).countDown();
            }
        }

        public int getCounts(IntentEvent.Type type) {
            return events.get(type).size();
        }

        public void setLatch(int count, IntentEvent.Type type) {
            latchMap.put(type, new CountDownLatch(count));
        }

        public void await(IntentEvent.Type type) {
            try {
                assertTrue("Timed out waiting for: " + type,
                        latchMap.get(type).await(5, TimeUnit.SECONDS));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private static class TestIntentTracker implements ObjectiveTrackerService {
        private TopologyChangeDelegate delegate;
        @Override
        public void setDelegate(TopologyChangeDelegate delegate) {
            this.delegate = delegate;
        }

        @Override
        public void unsetDelegate(TopologyChangeDelegate delegate) {
            if (delegate.equals(this.delegate)) {
                this.delegate = null;
            }
        }

        @Override
        public void addTrackedResources(Key key, Collection<NetworkResource> resources) {
            //TODO
        }

        @Override
        public void removeTrackedResources(Key key, Collection<NetworkResource> resources) {
            //TODO
        }

        @Override
        public void trackIntent(IntentData intentData) {
            //TODO
        }
    }

    private static class MockInstallableIntent extends FlowRuleIntent {

        public MockInstallableIntent() {
            super(APPID, Collections.singletonList(new MockFlowRule(100)), Collections.emptyList());
        }
    }

    private static class TestIntentCompiler implements IntentCompiler<MockIntent> {
        @Override
        public List<Intent> compile(MockIntent intent, List<Intent> installable) {
            return Lists.newArrayList(new MockInstallableIntent());
        }
    }

    private static class TestIntentCompilerMultipleFlows implements IntentCompiler<MockIntent> {
        @Override
        public List<Intent> compile(MockIntent intent, List<Intent> installable) {

            return IntStream.rangeClosed(1, 5)
                            .mapToObj(mock -> (new MockInstallableIntent()))
                            .collect(Collectors.toList());
        }
    }


    private static class TestIntentCompilerError implements IntentCompiler<MockIntent> {
        @Override
        public List<Intent> compile(MockIntent intent, List<Intent> installable) {
            throw new IntentCompilationException("Compilation always fails");
        }
    }

    /**
     * Hamcrest matcher to check that a collection of Intents contains an
     * Intent with the specified Intent Id.
     */
    public static class EntryForIntentMatcher extends TypeSafeMatcher<Collection<Intent>> {
        private final IntentId id;

        public EntryForIntentMatcher(IntentId idValue) {
            id = idValue;
        }

        @Override
        public boolean matchesSafely(Collection<Intent> intents) {
            for (Intent intent : intents) {
                if (intent.id().equals(id)) {
                    return true;
                }
            }
            return false;
        }

        @Override
        public void describeTo(Description description) {
            description.appendText("an intent with id \" ").
                    appendText(id.toString()).
                    appendText("\"");
        }
    }

    private static EntryForIntentMatcher hasIntentWithId(IntentId id) {
        return new EntryForIntentMatcher(id);
    }

    @Before
    public void setUp() {
        manager = new IntentManager();
        flowRuleService = new MockFlowRuleService();
        manager.store = new SimpleIntentStore();
        injectEventDispatcher(manager, new TestEventDispatcher());
        manager.trackerService = new TestIntentTracker();
        manager.flowRuleService = flowRuleService;
        manager.coreService = new TestCoreManager();
        manager.configService = mock(ComponentConfigService.class);
        service = manager;
        extensionService = manager;

        manager.activate();
        service.addListener(listener);
        extensionService.registerCompiler(MockIntent.class, compiler);

        assertTrue("store should be empty",
                   Sets.newHashSet(service.getIntents()).isEmpty());
        assertEquals(0L, flowRuleService.getFlowRuleCount());
    }

    public void verifyState() {
        // verify that all intents are parked and the batch operation is unblocked
        Set<IntentState> parked = Sets.newHashSet(INSTALLED, WITHDRAWN, FAILED, CORRUPT);
        for (Intent i : service.getIntents()) {
            IntentState state = service.getIntentState(i.key());
            assertTrue("Intent " + i.id() + " is in invalid state " + state,
                       parked.contains(state));
        }
        //the batch has not yet been removed when we receive the last event
        // FIXME: this doesn't guarantee to avoid the race

        //FIXME
//        for (int tries = 0; tries < 10; tries++) {
//            if (manager.batchService.getPendingOperations().isEmpty()) {
//                break;
//            }
//            delay(10);
//        }
//        assertTrue("There are still pending batch operations.",
//                   manager.batchService.getPendingOperations().isEmpty());

    }

    @After
    public void tearDown() {
        extensionService.unregisterCompiler(MockIntent.class);
        service.removeListener(listener);
        manager.deactivate();
        // TODO null the other refs?
    }

    @Test
    public void submitIntent() {
        flowRuleService.setFuture(true);

        listener.setLatch(1, Type.INSTALL_REQ);
        listener.setLatch(1, Type.INSTALLED);
        Intent intent = new MockIntent(MockIntent.nextId());
        service.submit(intent);
        listener.await(Type.INSTALL_REQ);
        listener.await(Type.INSTALLED);
        assertEquals(1L, service.getIntentCount());
        assertEquals(1L, flowRuleService.getFlowRuleCount());
        verifyState();
    }

    @Test
    public void withdrawIntent() {
        flowRuleService.setFuture(true);

        listener.setLatch(1, Type.INSTALLED);
        Intent intent = new MockIntent(MockIntent.nextId());
        service.submit(intent);
        listener.await(Type.INSTALLED);
        assertEquals(1L, service.getIntentCount());
        assertEquals(1L, flowRuleService.getFlowRuleCount());

        listener.setLatch(1, Type.WITHDRAWN);
        service.withdraw(intent);
        listener.await(Type.WITHDRAWN);
        assertEquals(0L, flowRuleService.getFlowRuleCount());
        verifyState();
    }

    @Test
    @Ignore("This is disabled because we are seeing intermittent failures on Jenkins")
    public void stressSubmitWithdrawUnique() {
        flowRuleService.setFuture(true);

        int count = 500;
        Intent[] intents = new Intent[count];

        listener.setLatch(count, Type.WITHDRAWN);

        for (int i = 0; i < count; i++) {
            intents[i] = new MockIntent(MockIntent.nextId());
            service.submit(intents[i]);
        }

        for (int i = 0; i < count; i++) {
            service.withdraw(intents[i]);
        }

        listener.await(Type.WITHDRAWN);
        assertEquals(0L, flowRuleService.getFlowRuleCount());
        verifyState();
    }

    @Test
    public void stressSubmitWithdrawSame() {
        flowRuleService.setFuture(true);

        int count = 50;

        Intent intent = new MockIntent(MockIntent.nextId());
        for (int i = 0; i < count; i++) {
            service.submit(intent);
            service.withdraw(intent);
        }

        assertAfter(SUBMIT_TIMEOUT_MS, () -> {
            assertEquals(1L, service.getIntentCount());
            assertEquals(0L, flowRuleService.getFlowRuleCount());
        });
        verifyState();
    }


    /**
     * Tests for proper behavior of installation of an intent that triggers
     * a compilation error.
     */
    @Test
    public void errorIntentCompile() {
        final TestIntentCompilerError errorCompiler = new TestIntentCompilerError();
        extensionService.registerCompiler(MockIntent.class, errorCompiler);
        MockIntent intent = new MockIntent(MockIntent.nextId());
        listener.setLatch(1, Type.INSTALL_REQ);
        listener.setLatch(1, Type.FAILED);
        service.submit(intent);
        listener.await(Type.INSTALL_REQ);
        listener.await(Type.FAILED);
        verifyState();
    }

    /**
     * Tests handling a future that contains an error as a result of
     * installing an intent.
     */
    @Ignore("skipping until we fix update ordering problem")
    @Test
    public void errorIntentInstallFromFlows() {
        final Long id = MockIntent.nextId();
        flowRuleService.setFuture(false);
        MockIntent intent = new MockIntent(id);
        listener.setLatch(1, Type.FAILED);
        listener.setLatch(1, Type.INSTALL_REQ);
        service.submit(intent);
        listener.await(Type.INSTALL_REQ);
        listener.await(Type.FAILED);
        // FIXME the intent will be moved into INSTALLED immediately which overrides FAILED
        // ... the updates come out of order
        verifyState();
    }

    /**
     * Tests handling a future that contains an unresolvable error as a result of
     * installing an intent.
     */
    @Test
    public void errorIntentInstallNeverTrue() {
        final Long id = MockIntent.nextId();
        flowRuleService.setFuture(false);
        MockIntent intent = new MockIntent(id);
        listener.setLatch(1, Type.CORRUPT);
        listener.setLatch(1, Type.INSTALL_REQ);
        service.submit(intent);
        listener.await(Type.INSTALL_REQ);
        // The delay here forces the retry loop in the intent manager to time out
        delay(100);
        flowRuleService.setFuture(false);
        service.withdraw(intent);
        listener.await(Type.CORRUPT);
        verifyState();
    }

    /**
     * Tests that a compiler for a subclass of an intent that already has a
     * compiler is automatically added.
     */
    @Test
    public void intentSubclassCompile() {
        class MockIntentSubclass extends MockIntent {
            public MockIntentSubclass(Long number) {
                super(number);
            }
        }
        flowRuleService.setFuture(true);

        listener.setLatch(1, Type.INSTALL_REQ);
        listener.setLatch(1, Type.INSTALLED);
        Intent intent = new MockIntentSubclass(MockIntent.nextId());
        service.submit(intent);
        listener.await(Type.INSTALL_REQ);
        listener.await(Type.INSTALLED);
        assertEquals(1L, service.getIntentCount());
        assertEquals(1L, flowRuleService.getFlowRuleCount());

        final Map<Class<? extends Intent>, IntentCompiler<? extends Intent>> compilers =
                extensionService.getCompilers();
        assertEquals(2, compilers.size());
        assertNotNull(compilers.get(MockIntentSubclass.class));
        assertNotNull(compilers.get(MockIntent.class));
        verifyState();
    }

    /**
     * Tests an intent with no compiler.
     */
    @Test
    public void intentWithoutCompiler() {
        class IntentNoCompiler extends Intent {
            IntentNoCompiler() {
                super(APPID, null, Collections.emptyList(),
                        Intent.DEFAULT_INTENT_PRIORITY);
            }
        }

        Intent intent = new IntentNoCompiler();
        listener.setLatch(1, Type.INSTALL_REQ);
        listener.setLatch(1, Type.FAILED);
        service.submit(intent);
        listener.await(Type.INSTALL_REQ);
        listener.await(Type.FAILED);
        verifyState();
    }

    /**
     * Tests an intent with no installer.
     */
    @Test
    public void intentWithoutInstaller() {
        MockIntent intent = new MockIntent(MockIntent.nextId());
        listener.setLatch(1, Type.INSTALL_REQ);
        listener.setLatch(1, Type.CORRUPT);
        service.submit(intent);
        listener.await(Type.INSTALL_REQ);
        listener.await(Type.CORRUPT);
        verifyState();
    }

    /**
     * Tests that the intent fetching methods are correct.
     */
    @Test
    public void testIntentFetching() {
        List<Intent> intents;

        flowRuleService.setFuture(true);

        intents = Lists.newArrayList(service.getIntents());
        assertThat(intents, hasSize(0));

        final MockIntent intent1 = new MockIntent(MockIntent.nextId());
        final MockIntent intent2 = new MockIntent(MockIntent.nextId());

        listener.setLatch(2, Type.INSTALL_REQ);
        listener.setLatch(2, Type.INSTALLED);
        service.submit(intent1);
        service.submit(intent2);
        listener.await(Type.INSTALL_REQ);
        listener.await(Type.INSTALL_REQ);
        listener.await(Type.INSTALLED);
        listener.await(Type.INSTALLED);

        intents = Lists.newArrayList(service.getIntents());
        assertThat(intents, hasSize(2));

        assertThat(intents, hasIntentWithId(intent1.id()));
        assertThat(intents, hasIntentWithId(intent2.id()));
        verifyState();
    }

    /**
     * Tests that removing all intents results in no flows remaining.
     */
    @Test
    public void testFlowRemoval() {
        List<Intent> intents;

        flowRuleService.setFuture(true);

        intents = Lists.newArrayList(service.getIntents());
        assertThat(intents, hasSize(0));

        final MockIntent intent1 = new MockIntent(MockIntent.nextId());
        final MockIntent intent2 = new MockIntent(MockIntent.nextId());

        listener.setLatch(1, Type.INSTALL_REQ);
        listener.setLatch(1, Type.INSTALLED);

        service.submit(intent1);
        listener.await(Type.INSTALL_REQ);
        listener.await(Type.INSTALLED);


        listener.setLatch(1, Type.INSTALL_REQ);
        listener.setLatch(1, Type.INSTALLED);

        service.submit(intent2);
        listener.await(Type.INSTALL_REQ);
        listener.await(Type.INSTALLED);

        assertThat(listener.getCounts(Type.INSTALLED), is(2));
        assertThat(flowRuleService.getFlowRuleCount(), is(2));

        listener.setLatch(1, Type.WITHDRAWN);
        service.withdraw(intent1);
        listener.await(Type.WITHDRAWN);

        listener.setLatch(1, Type.WITHDRAWN);
        service.withdraw(intent2);
        listener.await(Type.WITHDRAWN);

        assertThat(listener.getCounts(Type.WITHDRAWN), is(2));
        assertThat(flowRuleService.getFlowRuleCount(), is(0));
    }

    /**
     * Test failure to install an intent, then succeed on retry via IntentCleanup.
     */
    @Test
    public void testCorruptCleanup() {
        IntentCleanup cleanup = new IntentCleanup();
        cleanup.service = manager;
        cleanup.store = manager.store;
        cleanup.cfgService = new ComponentConfigAdapter();

        try {
            cleanup.activate();

            final TestIntentCompilerMultipleFlows errorCompiler = new TestIntentCompilerMultipleFlows();
            extensionService.registerCompiler(MockIntent.class, errorCompiler);
            List<Intent> intents;

            flowRuleService.setFuture(false);

            intents = Lists.newArrayList(service.getIntents());
            assertThat(intents, hasSize(0));

            final MockIntent intent1 = new MockIntent(MockIntent.nextId());

            listener.setLatch(1, Type.INSTALL_REQ);
            listener.setLatch(1, Type.CORRUPT);
            listener.setLatch(1, Type.INSTALLED);

            service.submit(intent1);

            listener.await(Type.INSTALL_REQ);
            listener.await(Type.CORRUPT);

            flowRuleService.setFuture(true);

            listener.await(Type.INSTALLED);

            assertThat(listener.getCounts(Type.CORRUPT), is(1));
            assertThat(listener.getCounts(Type.INSTALLED), is(1));
            assertEquals(INSTALLED, manager.getIntentState(intent1.key()));
            assertThat(flowRuleService.getFlowRuleCount(), is(5));
        } finally {
            cleanup.deactivate();
        }
    }

    /**
     * Test failure to install an intent, and verify retries.
     */
    @Test
    public void testCorruptRetry() {
        IntentCleanup cleanup = new IntentCleanup();
        cleanup.service = manager;
        cleanup.store = manager.store;
        cleanup.cfgService = new ComponentConfigAdapter();
        cleanup.period = 1_000_000;
        cleanup.retryThreshold = 3;

        try {
            cleanup.activate();

            final TestIntentCompilerMultipleFlows errorCompiler = new TestIntentCompilerMultipleFlows();
            extensionService.registerCompiler(MockIntent.class, errorCompiler);
            List<Intent> intents;

            flowRuleService.setFuture(false);

            intents = Lists.newArrayList(service.getIntents());
            assertThat(intents, hasSize(0));

            final MockIntent intent1 = new MockIntent(MockIntent.nextId());

            listener.setLatch(1, Type.INSTALL_REQ);
            listener.setLatch(cleanup.retryThreshold, Type.CORRUPT);
            listener.setLatch(1, Type.INSTALLED);

            service.submit(intent1);

            listener.await(Type.INSTALL_REQ);
            listener.await(Type.CORRUPT);
            assertEquals(CORRUPT, manager.getIntentState(intent1.key()));
            assertThat(listener.getCounts(Type.CORRUPT), is(cleanup.retryThreshold));

        } finally {
            cleanup.deactivate();
        }
    }

    /**
     * Tests that an intent that fails installation results in no flows remaining.
     */
    @Test
    @Ignore("MockFlowRule numbering issue") //test works if run independently
    public void testFlowRemovalInstallError() {
        final TestIntentCompilerMultipleFlows errorCompiler = new TestIntentCompilerMultipleFlows();
        extensionService.registerCompiler(MockIntent.class, errorCompiler);
        List<Intent> intents;

        flowRuleService.setFuture(true);
        //FIXME relying on "3" is brittle
        flowRuleService.setErrorFlow(3);

        intents = Lists.newArrayList(service.getIntents());
        assertThat(intents, hasSize(0));

        final MockIntent intent1 = new MockIntent(MockIntent.nextId());

        listener.setLatch(1, Type.INSTALL_REQ);
        listener.setLatch(1, Type.CORRUPT);

        service.submit(intent1);
        listener.await(Type.INSTALL_REQ);
        listener.await(Type.CORRUPT);

        assertThat(listener.getCounts(Type.CORRUPT), is(1));
        // in this test, there will still be flows abandoned on the data plane
        //assertThat(flowRuleService.getFlowRuleCount(), is(0));
    }
}
