/*
 * 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.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
    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();
        }
    }

}
