/*
 * 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.t3.impl;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.ChassisId;
import org.onlab.packet.EthType;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.cluster.NodeId;
import org.onosproject.mastership.MastershipServiceAdapter;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.DefaultDevice;
import org.onosproject.net.DefaultLink;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.Link;
import org.onosproject.net.PortNumber;
import org.onosproject.net.device.DeviceServiceAdapter;
import org.onosproject.net.driver.DefaultDriver;
import org.onosproject.net.driver.Driver;
import org.onosproject.net.driver.DriverServiceAdapter;
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowRuleServiceAdapter;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.criteria.Criterion;
import org.onosproject.net.flow.criteria.EthTypeCriterion;
import org.onosproject.net.flow.criteria.VlanIdCriterion;
import org.onosproject.net.group.Group;
import org.onosproject.net.group.GroupServiceAdapter;
import org.onosproject.net.host.HostServiceAdapter;
import org.onosproject.net.link.LinkServiceAdapter;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.t3.api.StaticPacketTrace;
import org.slf4j.Logger;

import java.util.HashMap;
import java.util.Set;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.onosproject.net.Device.Type.SWITCH;
import static org.onosproject.t3.impl.T3TestObjects.*;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Test Class for Troubleshoot Manager.
 */
public class TroubleshootManagerTest {

    private static final Logger log = getLogger(TroubleshootManager.class);

    private TroubleshootManager mngr;

    @Before
    public void setUp() throws Exception {
        mngr = new TroubleshootManager();
        mngr.flowRuleService = new TestFlowRuleService();
        mngr.hostService = new TestHostService();
        mngr.linkService = new TestLinkService();
        mngr.driverService = new TestDriverService();
        mngr.groupService = new TestGroupService();
        mngr.deviceService = new TestDeviceService();
        mngr.mastershipService = new TestMastershipService();

        assertNotNull("Manager should not be null", mngr);

        assertNotNull("Flow rule Service should not be null", mngr.flowRuleService);
        assertNotNull("Host Service should not be null", mngr.hostService);
        assertNotNull("Group Service should not be null", mngr.groupService);
        assertNotNull("Driver Service should not be null", mngr.driverService);
        assertNotNull("Link Service should not be null", mngr.linkService);
        assertNotNull("Device Service should not be null", mngr.deviceService);
    }

    /**
     * Tests failure on non existent device.
     */
    @Test(expected = NullPointerException.class)
    public void nonExistentDevice() {
        StaticPacketTrace traceFail = mngr.trace(PACKET_OK, ConnectPoint.deviceConnectPoint("nonexistent" + "/1"));
    }

    /**
     * Tests failure on offline device.
     */
    @Test
    public void offlineDevice() {
        StaticPacketTrace traceFail = mngr.trace(PACKET_OK, ConnectPoint.deviceConnectPoint(OFFLINE_DEVICE + "/1"));
        assertNotNull("Trace should not be null", traceFail);
        assertNull("Trace should have 0 output", traceFail.getGroupOuputs(SINGLE_FLOW_DEVICE));
    }

    /**
     * Tests failure on same output.
     */
    @Test
    public void sameOutput() {
        StaticPacketTrace traceFail = mngr.trace(PACKET_OK, SAME_OUTPUT_FLOW_CP);
        assertNotNull("Trace should not be null", traceFail);
        assertTrue("Trace should be unsuccessful",
                traceFail.resultMessage().contains("is same as initial input"));
        log.info("trace {}", traceFail.resultMessage());
    }

    /**
     * Tests ARP to controller.
     */
    @Test
    public void arpToController() {
        StaticPacketTrace traceSuccess = mngr.trace(PACKET_ARP, ARP_FLOW_CP);
        assertNotNull("Trace should not be null", traceSuccess);
        assertTrue("Trace should be successful",
                traceSuccess.resultMessage().contains("Packet goes to the controller"));
        assertTrue("Master should be Master1",
                traceSuccess.resultMessage().contains(MASTER_1));
        ConnectPoint connectPoint = traceSuccess.getGroupOuputs(ARP_FLOW_DEVICE).get(0).getOutput();
        assertEquals("Packet Should go to CONTROLLER", PortNumber.CONTROLLER, connectPoint.port());
        assertNull("VlanId should be null", traceSuccess.getGroupOuputs(ARP_FLOW_DEVICE).get(0)
                .getFinalPacket().getCriterion(Criterion.Type.VLAN_VID));
        log.info("trace {}", traceSuccess.resultMessage());
    }


    /**
     * Tests failure on device with no flows.
     */
    @Test
    public void noFlows() {
        StaticPacketTrace traceFail = mngr.trace(PACKET_OK, ConnectPoint.deviceConnectPoint("test/1"));
        assertNotNull("Trace should not be null", traceFail);
        assertNull("Trace should have 0 output", traceFail.getGroupOuputs(SINGLE_FLOW_DEVICE));
        log.info("trace {}", traceFail.resultMessage());
    }

    /**
     * Test a single flow rule that has output port in it.
     */
    @Test
    public void testSingleFlowRule() {

        testSuccess(PACKET_OK, SINGLE_FLOW_IN_CP, SINGLE_FLOW_DEVICE, SINGLE_FLOW_OUT_CP, 1, 1);

        testFailure(PACKET_FAIL, SINGLE_FLOW_IN_CP, SINGLE_FLOW_DEVICE);
    }

    /**
     * Tests two flow rule the last one of which has output port in it.
     */
    @Test
    public void testDualFlowRule() {

        //Test Success

        StaticPacketTrace traceSuccess = testSuccess(PACKET_OK, DUAL_FLOW_IN_CP, DUAL_FLOW_DEVICE,
                DUAL_FLOW_OUT_CP, 1, 1);

        //Testing Vlan
        Criterion criterion = traceSuccess.getGroupOuputs(DUAL_FLOW_DEVICE).get(0).
                getFinalPacket().getCriterion(Criterion.Type.VLAN_VID);
        assertNotNull("Packet Should have Vlan", criterion);

        VlanIdCriterion vlanIdCriterion = (VlanIdCriterion) criterion;

        assertEquals("Vlan should be 100", VlanId.vlanId((short) 100), vlanIdCriterion.vlanId());

        //Test Faliure
        testFailure(PACKET_FAIL, DUAL_FLOW_IN_CP, DUAL_FLOW_DEVICE);

    }

    /**
     * Test a single flow rule that points to a group with output port in it.
     */
    @Test
    public void flowAndGroup() throws Exception {

        StaticPacketTrace traceSuccess = testSuccess(PACKET_OK, GROUP_FLOW_IN_CP, GROUP_FLOW_DEVICE,
                GROUP_FLOW_OUT_CP, 1, 1);

        assertTrue("Wrong Output Group", traceSuccess.getGroupOuputs(GROUP_FLOW_DEVICE)
                .get(0).getGroups().contains(GROUP));
        assertEquals("Packet should not have MPLS Label", EthType.EtherType.IPV4.ethType(),
                ((EthTypeCriterion) traceSuccess.getGroupOuputs(GROUP_FLOW_DEVICE)
                        .get(0).getFinalPacket().getCriterion(Criterion.Type.ETH_TYPE)).ethType());
        assertNull("Packet should not have MPLS Label", traceSuccess.getGroupOuputs(GROUP_FLOW_DEVICE)
                .get(0).getFinalPacket().getCriterion(Criterion.Type.MPLS_LABEL));
        assertNull("Packet should not have MPLS Label", traceSuccess.getGroupOuputs(GROUP_FLOW_DEVICE)
                .get(0).getFinalPacket().getCriterion(Criterion.Type.MPLS_BOS));

    }

    /**
     * Test path through a 3 device topology.
     */
    @Test
    public void singlePathTopology() throws Exception {

        StaticPacketTrace traceSuccess = testSuccess(PACKET_OK_TOPO, TOPO_FLOW_1_IN_CP,
                TOPO_FLOW_3_DEVICE, TOPO_FLOW_3_OUT_CP, 1, 1);

        assertTrue("Incorrect path",
                traceSuccess.getCompletePaths().get(0).contains(TOPO_FLOW_2_IN_CP));
        assertTrue("Incorrect path",
                traceSuccess.getCompletePaths().get(0).contains(TOPO_FLOW_2_OUT_CP));
        assertTrue("Incorrect path",
                traceSuccess.getCompletePaths().get(0).contains(TOPO_FLOW_3_IN_CP));

    }

    /**
     * Test path through a 4 device topology with first device that has groups with multiple output buckets.
     */
    @Test
    public void testGroupTopo() throws Exception {

        StaticPacketTrace traceSuccess = testSuccess(PACKET_OK_TOPO, TOPO_FLOW_IN_CP,
                TOPO_FLOW_3_DEVICE, TOPO_FLOW_3_OUT_CP, 2, 1);

        log.info("{}", traceSuccess);

        assertTrue("Incorrect groups",
                traceSuccess.getGroupOuputs(TOPO_GROUP_FLOW_DEVICE).get(0).getGroups().contains(TOPO_GROUP));
        assertTrue("Incorrect bucket",
                traceSuccess.getGroupOuputs(TOPO_GROUP_FLOW_DEVICE).get(1).getGroups().contains(TOPO_GROUP));
    }

    /**
     * Test HW support in a single device with 2 flow rules to check hit of static HW rules.
     */
    @Test
    public void hardwareTest() throws Exception {

        StaticPacketTrace traceSuccess = testSuccess(PACKET_OK, HARDWARE_DEVICE_IN_CP,
                HARDWARE_DEVICE, HARDWARE_DEVICE_OUT_CP, 1, 1);

        assertEquals("wrong ETH type", EthType.EtherType.IPV4.ethType(),
                ((EthTypeCriterion) traceSuccess.getGroupOuputs(HARDWARE_DEVICE).get(0).getFinalPacket()
                        .getCriterion(Criterion.Type.ETH_TYPE)).ethType());

    }

    /**
     * Test dual links between 3 topology elements.
     */
    @Test
    public void dualLinks() throws Exception {

        StaticPacketTrace traceSuccess = testSuccess(PACKET_OK, DUAL_LINK_1_CP_1_IN,
                DUAL_LINK_3, DUAL_LINK_3_CP_3_OUT, 4, 1);

        //TODO tests

    }

    /**
     * Test proper clear deferred behaviour.
     */
    @Test
    public void clearDeferred() throws Exception {

        StaticPacketTrace traceSuccess = testSuccess(PACKET_OK, DEFERRED_CP_1_IN,
                DEFERRED_1, DEFERRED_CP_2_OUT, 1, 1);

        assertNull("MPLS should have been not applied due to clear deferred", traceSuccess
                .getGroupOuputs(DEFERRED_1).get(0).getFinalPacket().getCriterion(Criterion.Type.MPLS_LABEL));

    }


    private StaticPacketTrace testSuccess(TrafficSelector packet, ConnectPoint in, DeviceId deviceId, ConnectPoint out,
                                          int paths, int outputs) {
        StaticPacketTrace traceSuccess = mngr.trace(packet, in);

        log.info("trace {}", traceSuccess);

        log.info("trace {}", traceSuccess.resultMessage());

        assertNotNull("trace should not be null", traceSuccess);
        assertEquals("Trace should have " + outputs + " output", outputs,
                traceSuccess.getGroupOuputs(deviceId).size());
        assertEquals("Trace should only have " + paths + "output", paths, traceSuccess.getCompletePaths().size());
        assertTrue("Trace should be successful",
                traceSuccess.resultMessage().contains("Reached required destination Host"));
        assertEquals("Incorrect Output CP", out,
                traceSuccess.getGroupOuputs(deviceId).get(0).getOutput());

        return traceSuccess;
    }

    private void testFailure(TrafficSelector packet, ConnectPoint in, DeviceId deviceId) {
        StaticPacketTrace traceFail = mngr.trace(packet, in);

        log.info("trace {}", traceFail.resultMessage());

        assertNotNull("Trace should not be null", traceFail);
        assertNull("Trace should have 0 output", traceFail.getGroupOuputs(deviceId));
    }

    private class TestFlowRuleService extends FlowRuleServiceAdapter {
        @Override
        public Iterable<FlowEntry> getFlowEntries(DeviceId deviceId) {
            if (deviceId.equals(SINGLE_FLOW_DEVICE)) {
                return ImmutableList.of(SINGLE_FLOW_ENTRY);
            } else if (deviceId.equals(DUAL_FLOW_DEVICE)) {
                return ImmutableList.of(FIRST_FLOW_ENTRY, SECOND_FLOW_ENTRY);
            } else if (deviceId.equals(GROUP_FLOW_DEVICE)) {
                return ImmutableList.of(GROUP_FLOW_ENTRY);
            } else if (deviceId.equals(TOPO_FLOW_DEVICE) ||
                    deviceId.equals(TOPO_FLOW_2_DEVICE) ||
                    deviceId.equals(TOPO_FLOW_3_DEVICE) ||
                    deviceId.equals(TOPO_FLOW_4_DEVICE)) {
                return ImmutableList.of(TOPO_SINGLE_FLOW_ENTRY, TOPO_SECOND_INPUT_FLOW_ENTRY);
            } else if (deviceId.equals(TOPO_GROUP_FLOW_DEVICE)) {
                return ImmutableList.of(TOPO_GROUP_FLOW_ENTRY);
            } else if (deviceId.equals(HARDWARE_DEVICE)) {
                return ImmutableList.of(HARDWARE_ETH_FLOW_ENTRY, HARDWARE_FLOW_ENTRY);
            } else if (deviceId.equals(SAME_OUTPUT_FLOW_DEVICE)) {
                return ImmutableList.of(SAME_OUTPUT_FLOW_ENTRY);
            } else if (deviceId.equals(ARP_FLOW_DEVICE)) {
                return ImmutableList.of(ARP_FLOW_ENTRY);
            } else if (deviceId.equals(DUAL_LINK_1)) {
                return ImmutableList.of(DUAL_LINK_1_GROUP_FLOW_ENTRY);
            } else if (deviceId.equals(DUAL_LINK_2)) {
                return ImmutableList.of(DUAL_LINK_1_GROUP_FLOW_ENTRY, DUAL_LINK_2_GROUP_FLOW_ENTRY);
            } else if (deviceId.equals(DUAL_LINK_3)) {
                return ImmutableList.of(DUAL_LINK_3_FLOW_ENTRY, DUAL_LINK_3_FLOW_ENTRY_2);
            } else if (deviceId.equals(DEFERRED_1)) {
                return ImmutableList.of(DEFERRED_FLOW_ENTRY, DEFERRED_CLEAR_FLOW_ENTRY);
            }
            return ImmutableList.of();
        }
    }

    private class TestDriverService extends DriverServiceAdapter {
        @Override
        public Driver getDriver(DeviceId deviceId) {
            if (deviceId.equals(HARDWARE_DEVICE)) {
                return new DefaultDriver("ofdpa", ImmutableList.of(),
                        "test", "test", "test", new HashMap<>(), new HashMap<>());
            }
            return new DefaultDriver("NotHWDriver", ImmutableList.of(),
                    "test", "test", "test", new HashMap<>(), new HashMap<>());
        }
    }

    private class TestGroupService extends GroupServiceAdapter {
        @Override
        public Iterable<Group> getGroups(DeviceId deviceId) {
            if (deviceId.equals(GROUP_FLOW_DEVICE)) {
                return ImmutableList.of(GROUP);
            } else if (deviceId.equals(TOPO_GROUP_FLOW_DEVICE)) {
                return ImmutableList.of(TOPO_GROUP);
            } else if (deviceId.equals(DUAL_LINK_1) || deviceId.equals(DUAL_LINK_2)) {
                return ImmutableList.of(DUAL_LINK_GROUP);
            }
            return ImmutableList.of();
        }
    }

    private class TestHostService extends HostServiceAdapter {
        @Override
        public Set<Host> getConnectedHosts(ConnectPoint connectPoint) {
            if (connectPoint.equals(TOPO_FLOW_3_OUT_CP)) {
                return ImmutableSet.of(H2);
            } else if (connectPoint.equals(DUAL_LINK_1_CP_2_OUT) || connectPoint.equals(DUAL_LINK_1_CP_3_OUT) ||
                    connectPoint.equals(DUAL_LINK_2_CP_2_OUT) || connectPoint.equals(DUAL_LINK_2_CP_3_OUT)) {
                return ImmutableSet.of();
            }
            return ImmutableSet.of(H1);
        }

        @Override
        public Set<Host> getHostsByMac(MacAddress mac) {
            if (mac.equals(H1.mac())) {
                return ImmutableSet.of(H1);
            } else if (mac.equals(H2.mac())) {
                return ImmutableSet.of(H2);
            }
            return ImmutableSet.of();
        }

        @Override
        public Set<Host> getHostsByIp(IpAddress ip) {
            if ((H1.ipAddresses().contains(ip))) {
                return ImmutableSet.of(H1);
            } else if ((H2.ipAddresses().contains(ip))) {
                return ImmutableSet.of(H2);
            }
            return ImmutableSet.of();
        }
    }

    private class TestLinkService extends LinkServiceAdapter {
        @Override
        public Set<Link> getEgressLinks(ConnectPoint connectPoint) {
            if (connectPoint.equals(TOPO_FLOW_1_OUT_CP)
                    || connectPoint.equals(TOPO_FLOW_OUT_CP_1)) {
                return ImmutableSet.of(DefaultLink.builder()
                        .providerId(ProviderId.NONE)
                        .type(Link.Type.DIRECT)
                        .src(connectPoint)
                        .dst(TOPO_FLOW_2_IN_CP)
                        .build());
            } else if (connectPoint.equals(TOPO_FLOW_2_OUT_CP)) {
                return ImmutableSet.of(DefaultLink.builder()
                        .providerId(ProviderId.NONE)
                        .type(Link.Type.DIRECT)
                        .src(TOPO_FLOW_2_OUT_CP)
                        .dst(TOPO_FLOW_3_IN_CP)
                        .build());
            } else if (connectPoint.equals(TOPO_FLOW_OUT_CP_2)) {
                return ImmutableSet.of(DefaultLink.builder()
                        .providerId(ProviderId.NONE)
                        .type(Link.Type.DIRECT)
                        .src(TOPO_FLOW_OUT_CP_2)
                        .dst(TOPO_FLOW_4_IN_CP)
                        .build());
            } else if (connectPoint.equals(TOPO_FLOW_4_OUT_CP)) {
                return ImmutableSet.of(DefaultLink.builder()
                        .providerId(ProviderId.NONE)
                        .type(Link.Type.DIRECT)
                        .src(TOPO_FLOW_4_OUT_CP)
                        .dst(TOPO_FLOW_3_IN_2_CP)
                        .build());
            } else if (connectPoint.equals(DUAL_LINK_1_CP_2_OUT)) {
                return ImmutableSet.of(DefaultLink.builder()
                        .providerId(ProviderId.NONE)
                        .type(Link.Type.DIRECT)
                        .src(DUAL_LINK_1_CP_2_OUT)
                        .dst(DUAL_LINK_2_CP_1_IN)
                        .build());
            } else if (connectPoint.equals(DUAL_LINK_1_CP_3_OUT)) {
                return ImmutableSet.of(DefaultLink.builder()
                        .providerId(ProviderId.NONE)
                        .type(Link.Type.DIRECT)
                        .src(DUAL_LINK_1_CP_3_OUT)
                        .dst(DUAL_LINK_2_CP_4_IN)
                        .build());
            } else if (connectPoint.equals(DUAL_LINK_2_CP_2_OUT)) {
                return ImmutableSet.of(DefaultLink.builder()
                        .providerId(ProviderId.NONE)
                        .type(Link.Type.DIRECT)
                        .src(DUAL_LINK_2_CP_2_OUT)
                        .dst(DUAL_LINK_3_CP_1_IN)
                        .build());
            } else if (connectPoint.equals(DUAL_LINK_2_CP_3_OUT)) {
                return ImmutableSet.of(DefaultLink.builder()
                        .providerId(ProviderId.NONE)
                        .type(Link.Type.DIRECT)
                        .src(DUAL_LINK_2_CP_3_OUT)
                        .dst(DUAL_LINK_3_CP_2_IN)
                        .build());
            }
            return ImmutableSet.of();
        }
    }

    private class TestDeviceService extends DeviceServiceAdapter {
        @Override
        public Device getDevice(DeviceId deviceId) {
            if (deviceId.equals(DeviceId.deviceId("nonexistent"))) {
                return null;
            }
            return new DefaultDevice(ProviderId.NONE, DeviceId.deviceId("test"), SWITCH,
                    "test", "test", "test", "test", new ChassisId(),
                    DefaultAnnotations.builder().set("foo", "bar").build());
        }

        @Override
        public boolean isAvailable(DeviceId deviceId) {
            if (deviceId.equals(OFFLINE_DEVICE)) {
                return false;
            }
            return true;
        }
    }

    private class TestMastershipService extends MastershipServiceAdapter {
        @Override
        public NodeId getMasterFor(DeviceId deviceId) {
            return NodeId.nodeId(MASTER_1);
        }
    }
}