/*
 * Copyright 2018-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.openstacknetworking.impl;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.MoreExecutors;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.junit.TestUtils;
import org.onlab.packet.IpAddress;
import org.onosproject.cluster.ClusterServiceAdapter;
import org.onosproject.cluster.LeadershipServiceAdapter;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreServiceAdapter;
import org.onosproject.core.DefaultApplicationId;
import org.onosproject.net.DeviceId;
import org.onosproject.net.flow.DefaultFlowRule;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.FlowRuleOperation;
import org.onosproject.net.flow.FlowRuleOperations;
import org.onosproject.net.flow.FlowRuleServiceAdapter;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.openstacknode.api.DefaultOpenstackNode;
import org.onosproject.openstacknode.api.NodeState;
import org.onosproject.openstacknode.api.OpenstackNode;

import java.util.List;
import java.util.Map;
import java.util.Set;

import static org.junit.Assert.assertEquals;
import static org.onosproject.openstacknetworking.api.Constants.ACL_EGRESS_TABLE;
import static org.onosproject.openstacknetworking.api.Constants.ACL_INGRESS_TABLE;
import static org.onosproject.openstacknetworking.api.Constants.ARP_TABLE;
import static org.onosproject.openstacknetworking.api.Constants.DHCP_TABLE;
import static org.onosproject.openstacknetworking.api.Constants.FLAT_TABLE;
import static org.onosproject.openstacknetworking.api.Constants.FORWARDING_TABLE;
import static org.onosproject.openstacknetworking.api.Constants.JUMP_TABLE;
import static org.onosproject.openstacknetworking.api.Constants.STAT_FLAT_OUTBOUND_TABLE;
import static org.onosproject.openstacknetworking.api.Constants.STAT_INBOUND_TABLE;
import static org.onosproject.openstacknetworking.api.Constants.STAT_OUTBOUND_TABLE;
import static org.onosproject.openstacknetworking.api.Constants.VTAG_TABLE;
import static org.onosproject.openstacknetworking.api.Constants.VTAP_FLAT_OUTBOUND_TABLE;
import static org.onosproject.openstacknetworking.api.Constants.VTAP_INBOUND_TABLE;
import static org.onosproject.openstacknetworking.api.Constants.VTAP_OUTBOUND_TABLE;

/**
 * Unit tests for flow rule manager.
 */
public class OpenstackFlowRuleManagerTest {

    private static final ApplicationId TEST_APP_ID =
                                        new DefaultApplicationId(1, "test");

    private static final int DROP_PRIORITY = 0;

    private static final DeviceId DEVICE_ID = DeviceId.deviceId("of:000000000000000a");

    private OpenstackFlowRuleManager target;

    private Set<FlowRuleOperation> fros;

    /**
     * Initial setup for this unit test.
     */
    @Before
    public void setUp() {
        target = new OpenstackFlowRuleManager();
        TestUtils.setField(target, "coreService", new TestCoreService());
        TestUtils.setField(target, "flowRuleService", new TestFlowRuleService());
        TestUtils.setField(target, "clusterService", new TestClusterService());
        TestUtils.setField(target, "leadershipService", new TestLeadershipService());
        TestUtils.setField(target, "osNodeService", new TestOpenstackNodeService());
        TestUtils.setField(target, "deviceEventExecutor", MoreExecutors.newDirectExecutorService());

        target.activate();
    }

    /**
     * Tears down of this unit test.
     */
    @After
    public void tearDown() {
        target.deactivate();
        target = null;
    }

    /**
     * Tests whether the set rule method installs the flow rules properly.
     */
    @Test
    public void testSetRule() {
        int testPriority = 10;
        int testTableType = 10;

        fros = Sets.newConcurrentHashSet();

        TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
        TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();

        FlowRule.Builder flowRuleBuilder = DefaultFlowRule.builder()
                .forDevice(DEVICE_ID)
                .withSelector(selectorBuilder.build())
                .withTreatment(treatmentBuilder.build())
                .withPriority(testPriority)
                .fromApp(TEST_APP_ID)
                .forTable(testTableType)
                .makePermanent();

        target.setRule(TEST_APP_ID, DEVICE_ID, selectorBuilder.build(),
                treatmentBuilder.build(), testPriority, testTableType, true);
        validateFlowRule(flowRuleBuilder.build());
    }

    /**
     * Tests whether the connect tables method installs the flow rules properly.
     */
    @Test
    public void testConnectTables() {
        int testFromTable = 1;
        int testToTable = 2;

        fros = Sets.newConcurrentHashSet();

        TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
        TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();

        target.connectTables(DEVICE_ID, testFromTable, testToTable);

        FlowRule.Builder flowRuleBuilder = DefaultFlowRule.builder()
                .forDevice(DEVICE_ID)
                .withSelector(selectorBuilder.build())
                .withTreatment(treatmentBuilder.transition(testToTable).build())
                .withPriority(DROP_PRIORITY)
                .fromApp(TEST_APP_ID)
                .forTable(testFromTable)
                .makePermanent();

        validateFlowRule(flowRuleBuilder.build());
    }

    /**
     * Tests whether the setup table miss entry method installs the flow rules properly.
     */
    @Test
    public void testSetUpTableMissEntry() {
        int testTable = 10;

        fros = Sets.newConcurrentHashSet();

        TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
        TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();

        target.setUpTableMissEntry(DEVICE_ID, testTable);

        FlowRule.Builder flowRuleBuilder = DefaultFlowRule.builder()
                .forDevice(DEVICE_ID)
                .withSelector(selectorBuilder.build())
                .withTreatment(treatmentBuilder.drop().build())
                .withPriority(DROP_PRIORITY)
                .fromApp(TEST_APP_ID)
                .forTable(testTable)
                .makePermanent();

        validateFlowRule(flowRuleBuilder.build());
    }

    /**
     * Tests whether initialize pipeline method installs the flow rules properly.
     */
    @Test
    public void testInitializePipeline() {

        fros = Sets.newConcurrentHashSet();

        target.initializePipeline(DEVICE_ID);
        assertEquals("Flow Rule size was not match", 13, fros.size());

        Map<Integer, Integer> fromToTableMap = Maps.newConcurrentMap();
        fromToTableMap.put(STAT_INBOUND_TABLE, VTAP_INBOUND_TABLE);
        fromToTableMap.put(VTAP_INBOUND_TABLE, DHCP_TABLE);
        fromToTableMap.put(DHCP_TABLE, VTAG_TABLE);
        fromToTableMap.put(VTAG_TABLE, ARP_TABLE);
        fromToTableMap.put(ARP_TABLE, ACL_INGRESS_TABLE);
        fromToTableMap.put(ACL_EGRESS_TABLE, JUMP_TABLE);
        fromToTableMap.put(STAT_OUTBOUND_TABLE, VTAP_OUTBOUND_TABLE);
        fromToTableMap.put(VTAP_OUTBOUND_TABLE, FORWARDING_TABLE);
        fromToTableMap.put(STAT_FLAT_OUTBOUND_TABLE, VTAP_FLAT_OUTBOUND_TABLE);
        fromToTableMap.put(VTAP_FLAT_OUTBOUND_TABLE, FLAT_TABLE);

        fros.stream().map(FlowRuleOperation::rule).forEach(fr -> {
            if (fr.tableId() != JUMP_TABLE && fr.tableId() != FLAT_TABLE) {
                assertEquals("To Table did not match,",
                        fromToTableMap.get(fr.tableId()),
                        fr.treatment().tableTransition().tableId());
            }
        });
    }

    private void validateFlowRule(FlowRule ref) {
        assertEquals("Flow Rule size was not match", 1, fros.size());
        List<FlowRuleOperation> froList = Lists.newArrayList();
        froList.addAll(fros);
        FlowRuleOperation fro = froList.get(0);
        FlowRule fr = fro.rule();

        assertEquals("Application ID did not match", ref.appId(), fr.appId());
        assertEquals("Device ID did not match", ref.deviceId(), fr.deviceId());
        assertEquals("Selector did not match", ref.selector(), fr.selector());
        assertEquals("Treatment did not match", ref.treatment(), fr.treatment());
        assertEquals("Priority did not match", ref.priority(), fr.priority());
        assertEquals("Table ID did not match", ref.table(), fr.table());
        assertEquals("Permanent did not match", ref.isPermanent(), fr.isPermanent());
    }

    private class TestOpenstackNodeService extends OpenstackNodeServiceAdapter {
        @Override
        public OpenstackNode node(DeviceId deviceId) {
            return DefaultOpenstackNode.builder()
                    .hostname("host")
                    .type(OpenstackNode.NodeType.COMPUTE)
                    .state(NodeState.COMPLETE)
                    .managementIp(IpAddress.valueOf("1.1.1.1"))
                    .dataIp(IpAddress.valueOf("1.1.1.1"))
                    .build();
        }
    }

    private class TestFlowRuleService extends FlowRuleServiceAdapter {
        @Override
        public void apply(FlowRuleOperations ops) {
            fros.addAll(ops.stages().get(0));
        }
    }

    private class TestCoreService extends CoreServiceAdapter {

        @Override
        public ApplicationId registerApplication(String name) {
            return TEST_APP_ID;
        }
    }

    private class TestClusterService extends ClusterServiceAdapter {
    }

    private class TestLeadershipService extends LeadershipServiceAdapter {
    }
}
