/*
 * Copyright 2017-present Open Networking Foundation
 *
 * 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.vpls;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.onosproject.cluster.ClusterServiceAdapter;
import org.onosproject.cluster.Leader;
import org.onosproject.cluster.Leadership;
import org.onosproject.cluster.LeadershipEvent;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.EncapsulationType;
import org.onosproject.net.Host;
import org.onosproject.net.host.HostServiceAdapter;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentData;
import org.onosproject.net.intent.IntentEvent;
import org.onosproject.net.intent.IntentState;
import org.onosproject.net.intent.MockIdGenerator;
import org.onosproject.store.service.WallClockTimestamp;
import org.onosproject.vpls.api.VplsData;
import org.onosproject.vpls.api.VplsOperation;

import java.util.ArrayDeque;
import java.util.Collection;
import java.util.Deque;
import java.util.Set;

import static org.junit.Assert.*;
import static org.onlab.junit.TestTools.assertAfter;
import static org.onlab.junit.TestTools.delay;

/**
 * Tests for {@link VplsOperationManager}.
 */
public class VplsOperationManagerTest extends VplsTest {

    VplsOperationManager vplsOperationManager;
    private static final int OPERATION_DELAY = 1000;
    private static final int OPERATION_DURATION = 1500;

    @Before
    public void setup() {
        MockIdGenerator.cleanBind();
        vplsOperationManager = new VplsOperationManager();
        vplsOperationManager.coreService = new TestCoreService();
        vplsOperationManager.intentService = new TestIntentService();
        vplsOperationManager.leadershipService = new TestLeadershipService();
        vplsOperationManager.clusterService = new ClusterServiceAdapter();
        vplsOperationManager.hostService = new TestHostService();
        vplsOperationManager.vplsStore = new TestVplsStore();
        vplsOperationManager.isLeader = true;
        vplsOperationManager.activate();
    }

    @After
    public void tearDown() {
        MockIdGenerator.unbind();
        vplsOperationManager.deactivate();
    }

    /**
     * Sends leadership event to the manager and checks if the manager is
     * leader or not.
     */
    @Test
    public void testLeadershipEvent() {
        vplsOperationManager.isLeader = false;
        vplsOperationManager.localNodeId = NODE_ID_1;

        // leader changed to self
        Leader leader = new Leader(NODE_ID_1, 0, 0);
        Leadership leadership = new Leadership(APP_NAME, leader, ImmutableList.of());
        LeadershipEvent event = new LeadershipEvent(LeadershipEvent.Type.LEADER_CHANGED, leadership);
        ((TestLeadershipService) vplsOperationManager.leadershipService).sendEvent(event);
        assertTrue(vplsOperationManager.isLeader);

        // leader changed to other
        leader = new Leader(NODE_ID_2, 0, 0);
        leadership = new Leadership(APP_NAME, leader, ImmutableList.of());
        event = new LeadershipEvent(LeadershipEvent.Type.LEADER_CHANGED, leadership);
        ((TestLeadershipService) vplsOperationManager.leadershipService).sendEvent(event);
        assertFalse(vplsOperationManager.isLeader);
    }

    /**
     * Submits an ADD operation to the operation manager; check if the VPLS
     * store changed after a period.
     */
    @Test
    public void testSubmitAddOperation() {
        VplsData vplsData = VplsData.of(VPLS1);
        vplsData.addInterfaces(ImmutableSet.of(V100H1, V100H2));

        VplsOperation vplsOperation = VplsOperation.of(vplsData,
                                                       VplsOperation.Operation.ADD);

        vplsOperationManager.submit(vplsOperation);
        assertAfter(OPERATION_DELAY, OPERATION_DURATION, () -> {
            Collection<VplsData> vplss = vplsOperationManager.vplsStore.getAllVpls();
            assertEquals(1, vplss.size());
            VplsData result = vplss.iterator().next();

            assertEquals(vplsData, result);
            assertEquals(VplsData.VplsState.ADDED, result.state());

            Set<Intent> intentsInstalled =
                    Sets.newHashSet(vplsOperationManager.intentService.getIntents());
            assertEquals(4, intentsInstalled.size());
        });
    }

    /**
     * Submits an ADD operation to the operation manager; check the VPLS state
     * from store if Intent install failed.
     */
    @Test
    public void testSubmitAddOperationFail() {
        vplsOperationManager.intentService = new AlwaysFailureIntentService();
        VplsData vplsData = VplsData.of(VPLS1);
        vplsData.addInterfaces(ImmutableSet.of(V100H1, V100H2));

        VplsOperation vplsOperation = VplsOperation.of(vplsData,
                                                       VplsOperation.Operation.ADD);
        vplsOperationManager.submit(vplsOperation);
        assertAfter(OPERATION_DELAY, OPERATION_DURATION, () -> {
            Collection<VplsData> vplss = vplsOperationManager.vplsStore.getAllVpls();
            assertEquals(1, vplss.size());
            VplsData result = vplss.iterator().next();

            assertEquals(vplsData, result);
            assertEquals(VplsData.VplsState.FAILED, result.state());
        });
    }

    /**
     * Submits an REMOVE operation to the operation manager; check if the VPLS
     * store changed after a period.
     */
    @Test
    public void testSubmitRemoveOperation() {
        VplsData vplsData = VplsData.of(VPLS1);
        vplsData.addInterfaces(ImmutableSet.of(V100H1, V100H2));
        vplsData.state(VplsData.VplsState.REMOVING);

        VplsOperation vplsOperation = VplsOperation.of(vplsData,
                                                       VplsOperation.Operation.REMOVE);

        vplsOperationManager.submit(vplsOperation);

        assertAfter(OPERATION_DELAY, OPERATION_DURATION, () -> {
            Collection<VplsData> vplss = vplsOperationManager.vplsStore.getAllVpls();
            assertEquals(0, vplss.size());
        });
    }

    /**
     * Submits an UPDATE operation with VPLS interface update to the operation manager; check if the VPLS
     * store changed after a period.
     */
    @Test
    public void testSubmitUpdateOperation() {
        VplsData vplsData = VplsData.of(VPLS1);
        vplsData.addInterfaces(ImmutableSet.of(V100H1));
        vplsData.state(VplsData.VplsState.ADDED);
        vplsOperationManager.vplsStore.addVpls(vplsData);

        vplsData = VplsData.of(VPLS1, EncapsulationType.VLAN);
        vplsData.addInterfaces(ImmutableSet.of(V100H1, V100H2));
        vplsData.state(VplsData.VplsState.UPDATING);

        VplsOperation vplsOperation = VplsOperation.of(vplsData,
                                                       VplsOperation.Operation.UPDATE);

        vplsOperationManager.submit(vplsOperation);

        assertAfter(OPERATION_DELAY, OPERATION_DURATION, () -> {
            Collection<VplsData> vplss = vplsOperationManager.vplsStore.getAllVpls();
            VplsData result = vplss.iterator().next();
            VplsData expected = VplsData.of(VPLS1, EncapsulationType.VLAN);
            expected.addInterfaces(ImmutableSet.of(V100H1, V100H2));
            expected.state(VplsData.VplsState.ADDED);

            assertEquals(1, vplss.size());
            assertEquals(expected, result);

            Set<Intent> intentsInstalled =
                    Sets.newHashSet(vplsOperationManager.intentService.getIntents());
            assertEquals(4, intentsInstalled.size());
        });
    }

    /**
     * Submits an UPDATE operation with VPLS host update to the operation manager; check if the VPLS
     * store changed after a period.
     */
    @Test
    public void testSubmitUpdateHostOperation() {
        vplsOperationManager.hostService = new EmptyHostService();
        VplsData vplsData = VplsData.of(VPLS1);
        vplsData.addInterfaces(ImmutableSet.of(V100H1, V100H2));

        VplsOperation vplsOperation = VplsOperation.of(vplsData,
                                                       VplsOperation.Operation.ADD);
        vplsOperationManager.submit(vplsOperation);
        delay(1000);
        vplsOperationManager.hostService = new TestHostService();

        vplsData = VplsData.of(VPLS1);
        vplsData.addInterfaces(ImmutableSet.of(V100H1, V100H2));
        vplsData.state(VplsData.VplsState.UPDATING);

        vplsOperation = VplsOperation.of(vplsData,
                                                       VplsOperation.Operation.UPDATE);

        vplsOperationManager.submit(vplsOperation);

        assertAfter(OPERATION_DELAY, OPERATION_DURATION, () -> {
            Collection<VplsData> vplss = vplsOperationManager.vplsStore.getAllVpls();
            VplsData result = vplss.iterator().next();
            VplsData expected = VplsData.of(VPLS1);
            expected.addInterfaces(ImmutableSet.of(V100H1, V100H2));
            expected.state(VplsData.VplsState.ADDED);
            assertEquals(1, vplss.size());
            assertEquals(expected, result);

            assertEquals(4, vplsOperationManager.intentService.getIntentCount());
        });
    }

    /**
     * Submits same operation twice to the manager; the manager should ignore
     * duplicated operation.
     */
    @Test
    @Ignore("Test is brittle - revisit")
    public void testDuplicateOperationInQueue() {
        VplsData vplsData = VplsData.of(VPLS1);
        vplsData.addInterfaces(ImmutableSet.of(V100H1, V100H2));

        VplsOperation vplsOperation = VplsOperation.of(vplsData,
                                                       VplsOperation.Operation.ADD);

        vplsOperationManager.submit(vplsOperation);
        vplsOperationManager.submit(vplsOperation);
        Deque<VplsOperation> opQueue = vplsOperationManager.pendingVplsOperations.get(VPLS1);
        assertEquals(1, opQueue.size());

        // Clear operation queue before scheduler process it
        opQueue.clear();
    }

    /**
     * Submits REMOVE operation after submits ADD operation; there should be no
     * pending or running operation in the manager.
     */
    @Test
    public void testDoNothingOperation() {
        VplsData vplsData = VplsData.of(VPLS1);
        vplsData.addInterfaces(ImmutableSet.of(V100H1, V100H2));

        VplsOperation vplsOperation = VplsOperation.of(vplsData,
                                                       VplsOperation.Operation.ADD);
        vplsOperationManager.submit(vplsOperation);
        vplsOperation = VplsOperation.of(vplsData,
                                         VplsOperation.Operation.REMOVE);
        vplsOperationManager.submit(vplsOperation);
        assertAfter(OPERATION_DELAY, OPERATION_DURATION, () -> {
            assertEquals(0, vplsOperationManager.pendingVplsOperations.size());

            // Should not have any running operation
            assertEquals(0, vplsOperationManager.runningOperations.size());
        });
    }

    /**
     * Optimize operations which don't need to be optimized.
     */
    @Test
    public void testOptimizeOperationsNoOptimize() {
        // empty queue
        Deque<VplsOperation> operations = new ArrayDeque<>();
        VplsOperation vplsOperation =
                VplsOperationManager.getOptimizedVplsOperation(operations);
        assertNull(vplsOperation);

        // one operation
        VplsData vplsData = VplsData.of(VPLS1);
        vplsOperation = VplsOperation.of(vplsData, VplsOperation.Operation.ADD);
        operations.add(vplsOperation);
        VplsOperation result =
                VplsOperationManager.getOptimizedVplsOperation(operations);
        assertEquals(vplsOperation, result);

    }

    /**
     * Optimize operations with first is ADD operation and last is also ADD
     * operation.
     */
    @Test
    public void testOptimizeOperationsAToA() {
        Deque<VplsOperation> operations = new ArrayDeque<>();
        VplsData vplsData = VplsData.of(VPLS1);
        vplsData.addInterfaces(ImmutableSet.of(V100H1));
        VplsOperation vplsOperation = VplsOperation.of(vplsData,
                                                       VplsOperation.Operation.ADD);
        operations.add(vplsOperation);
        vplsData = VplsData.of(VPLS1, EncapsulationType.VLAN);
        vplsData.addInterfaces(ImmutableSet.of(V100H1, V100H2));
        vplsOperation = VplsOperation.of(vplsData,
                                         VplsOperation.Operation.ADD);
        operations.add(vplsOperation);
        vplsOperation = VplsOperationManager.getOptimizedVplsOperation(operations);
        assertEquals(VplsOperation.of(vplsData, VplsOperation.Operation.ADD), vplsOperation);
    }

    /**
     * Optimize operations with first is ADD operation and last is REMOVE
     * operation.
     */
    @Test
    public void testOptimizeOperationsAToR() {
        Deque<VplsOperation> operations = new ArrayDeque<>();
        VplsData vplsData = VplsData.of(VPLS1);
        vplsData.addInterfaces(ImmutableSet.of(V100H1));
        VplsOperation vplsOperation = VplsOperation.of(vplsData,
                                                       VplsOperation.Operation.ADD);
        operations.add(vplsOperation);
        vplsOperation = VplsOperation.of(vplsData,
                                         VplsOperation.Operation.REMOVE);
        operations.add(vplsOperation);
        vplsOperation = VplsOperationManager.getOptimizedVplsOperation(operations);
        assertNull(vplsOperation);
    }

    /**
     * Optimize operations with first is ADD operation and last is UPDATE
     * operation.
     */
    @Test
    public void testOptimizeOperationsAToU() {
        Deque<VplsOperation> operations = new ArrayDeque<>();
        VplsData vplsData = VplsData.of(VPLS1);
        vplsData.addInterfaces(ImmutableSet.of(V100H1));
        VplsOperation vplsOperation = VplsOperation.of(vplsData,
                                                       VplsOperation.Operation.ADD);
        operations.add(vplsOperation);
        vplsData = VplsData.of(VPLS1, EncapsulationType.VLAN);
        vplsData.addInterfaces(ImmutableSet.of(V100H1, V100H2));
        vplsOperation = VplsOperation.of(vplsData,
                                         VplsOperation.Operation.UPDATE);
        operations.add(vplsOperation);
        vplsOperation = VplsOperationManager.getOptimizedVplsOperation(operations);
        assertEquals(VplsOperation.of(vplsData, VplsOperation.Operation.ADD), vplsOperation);
    }

    /**
     * Optimize operations with first is REMOVE operation and last is ADD
     * operation.
     */
    @Test
    public void testOptimizeOperationsRToA() {
        Deque<VplsOperation> operations = new ArrayDeque<>();
        VplsData vplsData = VplsData.of(VPLS1);
        vplsData.addInterfaces(ImmutableSet.of(V100H1));
        VplsOperation vplsOperation = VplsOperation.of(vplsData,
                                                       VplsOperation.Operation.REMOVE);
        operations.add(vplsOperation);
        vplsData = VplsData.of(VPLS1, EncapsulationType.VLAN);
        vplsData.addInterfaces(ImmutableSet.of(V100H1, V100H2));
        vplsOperation = VplsOperation.of(vplsData,
                                         VplsOperation.Operation.ADD);
        operations.add(vplsOperation);
        vplsOperation = VplsOperationManager.getOptimizedVplsOperation(operations);
        assertEquals(VplsOperation.of(vplsData, VplsOperation.Operation.UPDATE), vplsOperation);
    }

    /**
     * Optimize operations with first is REMOVE operation and last is also
     * REMOVE operation.
     */
    @Test
    public void testOptimizeOperationsRToR() {
        Deque<VplsOperation> operations = new ArrayDeque<>();
        VplsData vplsData = VplsData.of(VPLS1);
        vplsData.addInterfaces(ImmutableSet.of(V100H1));
        VplsOperation vplsOperation = VplsOperation.of(vplsData,
                                                       VplsOperation.Operation.REMOVE);
        operations.add(vplsOperation);
        vplsData = VplsData.of(VPLS1, EncapsulationType.VLAN);
        vplsData.addInterfaces(ImmutableSet.of(V100H1, V100H2));
        vplsOperation = VplsOperation.of(vplsData,
                                         VplsOperation.Operation.REMOVE);
        operations.add(vplsOperation);
        vplsOperation = VplsOperationManager.getOptimizedVplsOperation(operations);
        vplsData = VplsData.of(VPLS1);
        vplsData.addInterfaces(ImmutableSet.of(V100H1));
        assertEquals(VplsOperation.of(vplsData, VplsOperation.Operation.REMOVE), vplsOperation);
    }

    /**
     * Optimize operations with first is REMOVE operation and last is UPDATE
     * operation.
     */
    @Test
    public void testOptimizeOperationsRToU() {
        Deque<VplsOperation> operations = new ArrayDeque<>();
        VplsData vplsData = VplsData.of(VPLS1);
        vplsData.addInterfaces(ImmutableSet.of(V100H1));
        VplsOperation vplsOperation = VplsOperation.of(vplsData,
                                                       VplsOperation.Operation.REMOVE);
        operations.add(vplsOperation);
        vplsData = VplsData.of(VPLS1, EncapsulationType.VLAN);
        vplsData.addInterfaces(ImmutableSet.of(V100H1, V100H2));
        vplsOperation = VplsOperation.of(vplsData,
                                         VplsOperation.Operation.UPDATE);
        operations.add(vplsOperation);
        vplsOperation = VplsOperationManager.getOptimizedVplsOperation(operations);
        assertEquals(VplsOperation.of(vplsData, VplsOperation.Operation.UPDATE), vplsOperation);
    }

    /**
     * Optimize operations with first is UPDATE operation and last is ADD
     * operation.
     */
    @Test
    public void testOptimizeOperationsUToA() {
        Deque<VplsOperation> operations = new ArrayDeque<>();
        VplsData vplsData = VplsData.of(VPLS1);
        vplsData.addInterfaces(ImmutableSet.of(V100H1));
        VplsOperation vplsOperation = VplsOperation.of(vplsData,
                                                       VplsOperation.Operation.UPDATE);
        operations.add(vplsOperation);
        vplsData = VplsData.of(VPLS1, EncapsulationType.VLAN);
        vplsData.addInterfaces(ImmutableSet.of(V100H1, V100H2));
        vplsOperation = VplsOperation.of(vplsData,
                                         VplsOperation.Operation.ADD);
        operations.add(vplsOperation);
        vplsOperation = VplsOperationManager.getOptimizedVplsOperation(operations);
        assertEquals(VplsOperation.of(vplsData, VplsOperation.Operation.UPDATE), vplsOperation);
    }

    /**
     * Optimize operations with first is UPDATE operation and last is REMOVE
     * operation.
     */
    @Test
    public void testOptimizeOperationsUToR() {
        Deque<VplsOperation> operations = new ArrayDeque<>();
        VplsData vplsData = VplsData.of(VPLS1);
        vplsData.addInterfaces(ImmutableSet.of(V100H1));
        VplsOperation vplsOperation = VplsOperation.of(vplsData,
                                                       VplsOperation.Operation.UPDATE);
        operations.add(vplsOperation);
        vplsData = VplsData.of(VPLS1, EncapsulationType.VLAN);
        vplsData.addInterfaces(ImmutableSet.of(V100H1, V100H2));
        vplsOperation = VplsOperation.of(vplsData,
                                         VplsOperation.Operation.REMOVE);
        operations.add(vplsOperation);
        vplsOperation = VplsOperationManager.getOptimizedVplsOperation(operations);
        assertEquals(VplsOperation.of(vplsData, VplsOperation.Operation.REMOVE), vplsOperation);
    }

    /**
     * Optimize operations with first is UPDATE operation and last is also
     * UPDATE operation.
     */
    @Test
    public void testOptimizeOperationsUToU() {
        Deque<VplsOperation> operations = new ArrayDeque<>();
        VplsData vplsData = VplsData.of(VPLS1);
        vplsData.addInterfaces(ImmutableSet.of(V100H1));
        VplsOperation vplsOperation = VplsOperation.of(vplsData,
                                                       VplsOperation.Operation.UPDATE);
        operations.add(vplsOperation);
        vplsData = VplsData.of(VPLS1, EncapsulationType.VLAN);
        vplsData.addInterfaces(ImmutableSet.of(V100H1, V100H2));
        vplsOperation = VplsOperation.of(vplsData,
                                         VplsOperation.Operation.UPDATE);
        operations.add(vplsOperation);
        vplsOperation = VplsOperationManager.getOptimizedVplsOperation(operations);
        assertEquals(VplsOperation.of(vplsData, VplsOperation.Operation.UPDATE), vplsOperation);
    }

    /**
     * Test Intent service which always fail when submit or withdraw Intents.
     */
    class AlwaysFailureIntentService extends TestIntentService {
        @Override
        public void submit(Intent intent) {
            intents.add(new IntentData(intent, IntentState.FAILED, new WallClockTimestamp()));
            if (listener != null) {
                IntentEvent event = IntentEvent.getEvent(IntentState.FAILED, intent).get();
                listener.event(event);
            }
        }

        @Override
        public void withdraw(Intent intent) {
            intents.forEach(intentData -> {
                if (intentData.intent().key().equals(intent.key())) {
                    intentData.setState(IntentState.FAILED);

                    if (listener != null) {
                        IntentEvent event = IntentEvent.getEvent(IntentState.FAILED, intent).get();
                        listener.event(event);
                    }
                }
            });
        }
    }

    /**
     * Test host service without any hosts.
     */
    class EmptyHostService extends HostServiceAdapter {
        @Override
        public Set<Host> getConnectedHosts(ConnectPoint connectPoint) {
            return ImmutableSet.of();
        }
    }

}
