/*
 * Copyright 2016-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.net.optical.intent.impl.compiler;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Sets;
import org.junit.Before;
import org.junit.Test;
import org.onlab.graph.ScalarWeight;
import org.onlab.packet.ChassisId;
import org.onosproject.TestApplicationId;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.AbstractProjectableModel;
import org.onosproject.net.Annotations;
import org.onosproject.net.CltSignalType;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.DefaultDevice;
import org.onosproject.net.DefaultLink;
import org.onosproject.net.DefaultPath;
import org.onosproject.net.DefaultPort;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.OduSignalId;
import org.onosproject.net.OduSignalType;
import org.onosproject.net.OduSignalUtils;
import org.onosproject.net.OtuSignalType;
import org.onosproject.net.Path;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.TributarySlot;
import org.onosproject.net.device.DeviceServiceAdapter;
import org.onosproject.net.driver.DriverService;
import org.onosproject.net.driver.DriverServiceAdapter;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.Criteria;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.intent.AbstractIntentTest;
import org.onosproject.net.intent.FlowRuleIntent;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentExtensionService;
import org.onosproject.net.intent.Key;
import org.onosproject.net.intent.OpticalOduIntent;
import org.onosproject.net.optical.OduCltPort;
import org.onosproject.net.optical.OtuPort;
import org.onosproject.net.optical.impl.DefaultOduCltPort;
import org.onosproject.net.optical.impl.DefaultOtuPort;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.net.resource.MockResourceService;
import org.onosproject.net.topology.LinkWeigher;
import org.onosproject.net.topology.Topology;
import org.onosproject.net.topology.TopologyServiceAdapter;

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import static org.easymock.EasyMock.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.assertEquals;
import static org.onosproject.net.AnnotationKeys.PORT_NAME;
import static org.onosproject.net.AnnotationKeys.STATIC_PORT;
import static org.onosproject.net.Device.Type.OTN;
import static org.onosproject.net.DeviceId.deviceId;
import static org.onosproject.net.Link.Type.OPTICAL;
import static org.onosproject.net.NetTestTools.APP_ID;
import static org.onosproject.net.NetTestTools.PID;

public class OpticalOduIntentCompilerTest extends AbstractIntentTest {

    private static final String DEV1 = "of:1";
    private static final String DEV2 = "of:2";
    private static final String DEV3 = "of:3";

    static final Key KEY1 = Key.of(5L, APP_ID);

    private static final String STATIC_TRUE = "true";
    private static final String PNAME = "p2";

    private CoreService coreService;
    private IntentExtensionService intentExtensionService;
    private OpticalOduIntentCompiler sut;

    private final ApplicationId appId = new TestApplicationId("test");
    private static Device device1 = new DefaultDevice(ProviderId.NONE, deviceId(DEV1), OTN,
            "m", "h", "s", "n", new ChassisId(0L));
    private static Device device2 = new DefaultDevice(ProviderId.NONE, deviceId(DEV2), OTN,
            "m", "h", "s", "n", new ChassisId(1L));
    private static Device device3 = new DefaultDevice(ProviderId.NONE, deviceId(DEV3), OTN,
            "m", "h", "s", "n", new ChassisId(2L));

    private static Annotations annotations1 = DefaultAnnotations.builder().set(STATIC_PORT, STATIC_TRUE).build();
    private static Annotations annotations2 = DefaultAnnotations.builder().set(PORT_NAME, PNAME).build();

    // OduClt ports with signalType=1GBE
    private static final OduCltPort D1P1 =
            new DefaultOduCltPort(new DefaultPort(device1, PortNumber.portNumber(1), true, annotations1),
                                  CltSignalType.CLT_1GBE);
    private static final OduCltPort D3P2 =
            new DefaultOduCltPort(new DefaultPort(device3, PortNumber.portNumber(2), true, annotations1),
                                  CltSignalType.CLT_1GBE);

    // Otu ports with signalType=ODU2
    private static final OtuPort D1P2 =
            new DefaultOtuPort(new DefaultPort(device1, PortNumber.portNumber(2), true, annotations2),
                               OtuSignalType.OTU2);
    private static final OtuPort D2P1 =
            new DefaultOtuPort(new DefaultPort(device2, PortNumber.portNumber(1), true, annotations2),
                               OtuSignalType.OTU2);
    private static final OtuPort D2P2 =
            new DefaultOtuPort(new DefaultPort(device2, PortNumber.portNumber(2), true, annotations2),
                               OtuSignalType.OTU2);
    private static final OtuPort D3P1 =
            new DefaultOtuPort(new DefaultPort(device3, PortNumber.portNumber(1), true, annotations2),
                               OtuSignalType.OTU2);

    // OduClt ports with signalType=10GBE
    private static final OduCltPort D1P3 =
            new DefaultOduCltPort(new DefaultPort(device1, PortNumber.portNumber(3), true, annotations1),
                                  CltSignalType.CLT_10GBE);
    private static final OduCltPort D3P3 =
            new DefaultOduCltPort(new DefaultPort(device3, PortNumber.portNumber(3), true, annotations1),
                                  CltSignalType.CLT_10GBE);

    // OduCltPort ConnectPoints
    private final ConnectPoint d1p1 = new ConnectPoint(device1.id(), D1P1.number());
    private final ConnectPoint d1p3 = new ConnectPoint(device1.id(), D1P3.number());
    private final ConnectPoint d3p2 = new ConnectPoint(device3.id(), D3P2.number());
    private final ConnectPoint d3p3 = new ConnectPoint(device3.id(), D3P3.number());

    // OtuPort ConnectPoints
    private final ConnectPoint d1p2 = new ConnectPoint(device1.id(), D1P2.number());
    private final ConnectPoint d2p1 = new ConnectPoint(device2.id(), D2P1.number());
    private final ConnectPoint d2p2 = new ConnectPoint(device2.id(), D2P2.number());
    private final ConnectPoint d3p1 = new ConnectPoint(device3.id(), D3P1.number());

    private final List<Link> links = Arrays.asList(
            DefaultLink.builder().providerId(PID).src(d1p2).dst(d2p1).type(OPTICAL).build(),
            DefaultLink.builder().providerId(PID).src(d2p2).dst(d3p1).type(OPTICAL).build()
    );
    private final Path path = new DefaultPath(PID, links, ScalarWeight.toWeight(3));

    private OpticalOduIntent intent;

    /**
     * Mocks the topology service to give paths in the test.
     */
    private class MockTopologyService extends TopologyServiceAdapter {
        Set<Path> paths = Sets.newHashSet(path);

        @Override
        public Set<Path> getPaths(Topology topology, DeviceId src, DeviceId dst, LinkWeigher weight) {
            return paths;
        }

        @Override
        public Topology currentTopology() {
            return null;
        }
    }

    /**
     * Mocks the device service so that devices and ports appear available in the test.
     */
    private static class MockDeviceService extends DeviceServiceAdapter {
        @Override
        public boolean isAvailable(DeviceId deviceId) {
            return true;
        }

        @Override
        public List<Port> getPorts(DeviceId deviceId) {
            if (deviceId.equals(deviceId(DEV1))) {
                return ImmutableList.of((Port) D1P1, (Port) D1P2, (Port) D1P3);
            }

            if (deviceId.equals(deviceId(DEV2))) {
                return ImmutableList.of((Port) D2P1, (Port) D2P2);
            }

            if (deviceId.equals(deviceId(DEV3))) {
                return ImmutableList.of((Port) D3P1, (Port) D3P2, (Port) D3P3);
            }

            return Collections.emptyList();
        }

        @Override
        public Port getPort(DeviceId deviceId, PortNumber portNumber) {
            if (deviceId.equals(deviceId(DEV1))) {
                switch (portNumber.toString()) {
                    case "1":
                        return D1P1;
                    case "2":
                        return D1P2;
                    case "3":
                        return D1P3;
                    default:
                        return null;
                }
            }
            if (deviceId.equals(deviceId(DEV2))) {
                switch (portNumber.toString()) {
                    case "1":
                        return D2P1;
                    case "2":
                        return D2P2;
                    default:
                        return null;
                }
            }
            if (deviceId.equals(deviceId(DEV3))) {
                switch (portNumber.toString()) {
                    case "1":
                        return D3P1;
                    case "2":
                        return D3P2;
                    case "3":
                        return D3P3;
                    default:
                        return null;
                }
            }
            return null;
        }
    }

    private static class MockDriverService extends DriverServiceAdapter
            implements DriverService {
        // TODO override to return appropriate driver,
        // with DefaultOpticalDevice support, etc.
    }

    @Before
    public void setUp() {
        AbstractProjectableModel.setDriverService(null, new MockDriverService());
        sut =  new OpticalOduIntentCompiler();
        coreService = createMock(CoreService.class);
        expect(coreService.registerApplication("org.onosproject.net.intent"))
                .andReturn(appId);
        sut.coreService = coreService;
        sut.deviceService = new MockDeviceService();
        sut.resourceService = new MockResourceService();
        sut.topologyService = new MockTopologyService();

        super.setUp();

        intentExtensionService = createMock(IntentExtensionService.class);
        intentExtensionService.registerCompiler(OpticalOduIntent.class, sut);
        intentExtensionService.unregisterCompiler(OpticalOduIntent.class);
        sut.intentManager = intentExtensionService;

        replay(coreService, intentExtensionService);
    }

    /**
     * Tests compile of OpticalOduIntent with allocation of TributarySlots.
     * Compile two ODUCLT ports (with CLT_1GBE), over OTU ports (with OTU2):
     *   - only one TributarySlot is used
     */
    @Test
    public void test1GbeMultiplexOverOdu2() {

        intent = OpticalOduIntent.builder()
                .appId(APP_ID)
                .key(KEY1)
                .src(d1p1)
                .dst(d3p2)
                .signalType(D1P1.signalType())
                .bidirectional(false)
                .build();

        sut.activate();

        List<Intent> compiled = sut.compile(intent, Collections.emptyList());
        assertThat(compiled, hasSize(1));

        assertThat("key is inherited",
                   compiled.stream().map(Intent::key).collect(Collectors.toList()),
                   everyItem(is(intent.key())));

        Collection<FlowRule> rules = ((FlowRuleIntent) compiled.get(0)).flowRules();

        // 1st Device
        FlowRule rule1 = rules.stream()
                .filter(x -> x.deviceId().equals(device1.id()))
                .findFirst()
                .get();
        // validate SRC selector
        TrafficSelector.Builder selectorBuilder1 = DefaultTrafficSelector.builder();
        selectorBuilder1.matchInPort(d1p1.port());
        selectorBuilder1.add(Criteria.matchOduSignalType(OduSignalType.ODU0));
        assertThat(rule1.selector(), is(selectorBuilder1.build()));

        // validate SRC treatment  (with OduSignalId, where 1 TributarySlot is used)
        TrafficTreatment.Builder treatmentBuilder1 = DefaultTrafficTreatment.builder();
        Set<TributarySlot> slots = new HashSet<>();
        slots.add(TributarySlot.of(1));
        OduSignalId oduSignalId = OduSignalUtils.buildOduSignalId(OduSignalType.ODU2, slots);
        treatmentBuilder1.add(Instructions.modL1OduSignalId(oduSignalId));
        treatmentBuilder1.setOutput(d1p2.port());
        assertThat(rule1.treatment(), is(treatmentBuilder1.build()));

        // 2nd Device
        FlowRule rule2 = rules.stream()
                .filter(x -> x.deviceId().equals(device2.id()))
                .findFirst()
                .get();
        // validate SRC selector
        TrafficSelector.Builder selectorBuilder2 = DefaultTrafficSelector.builder();
        selectorBuilder2.matchInPort(d2p1.port());
        selectorBuilder2.add(Criteria.matchOduSignalType(OduSignalType.ODU0));
        selectorBuilder2.add(Criteria.matchOduSignalId(oduSignalId));
        assertThat(rule2.selector(), is(selectorBuilder2.build()));

        // validate SRC treatment  (with OduSignalId, where 1 TributarySlot is used)
        TrafficTreatment.Builder treatmentBuilder2 = DefaultTrafficTreatment.builder();
        treatmentBuilder2.add(Instructions.modL1OduSignalId(oduSignalId));
        treatmentBuilder2.setOutput(d2p2.port());
        assertThat(rule2.treatment(), is(treatmentBuilder2.build()));


        // 3rd Device
        FlowRule rule3 = rules.stream()
                .filter(x -> x.deviceId().equals(device3.id()))
                .findFirst()
                .get();
        // validate DST selector (with OduSignalId, where the same TributarySlot is used)
        TrafficSelector.Builder selectorBuilder3 = DefaultTrafficSelector.builder();
        selectorBuilder3.matchInPort(d3p1.port());
        selectorBuilder3.add(Criteria.matchOduSignalType(OduSignalType.ODU0));
        selectorBuilder3.add(Criteria.matchOduSignalId(oduSignalId));
        assertThat(rule3.selector(), is(selectorBuilder3.build()));

        // validate DST treatment
        assertThat(rule3.treatment(), is(
                DefaultTrafficTreatment.builder().setOutput(d3p2.port()).build()
                ));

        rules.forEach(rule -> assertEquals("FlowRule priority is incorrect",
                intent.priority(), rule.priority()));

        sut.deactivate();
    }

    /**
     * Tests compile of OpticalOduIntent with allocation of TributarySlots.
     * Compile two ODUCLT ports (with CLT_10GBE), over OTU ports (with OTU2):
     *   - All TributarySlots are used
     */
    @Test
    public void test10GbeMultiplexOverOdu2() {

        intent = OpticalOduIntent.builder()
                .appId(APP_ID)
                .key(KEY1)
                .src(d1p3)
                .dst(d3p3)
                .signalType(D1P3.signalType())
                .bidirectional(false)
                .build();

        sut.activate();

        List<Intent> compiled = sut.compile(intent, Collections.emptyList());
        assertThat(compiled, hasSize(1));

        assertThat("key is inherited",
                   compiled.stream().map(Intent::key).collect(Collectors.toList()),
                   everyItem(is(intent.key())));

        Collection<FlowRule> rules = ((FlowRuleIntent) compiled.get(0)).flowRules();

        // 1st Device
        FlowRule rule1 = rules.stream()
                .filter(x -> x.deviceId().equals(device1.id()))
                .findFirst()
                .get();
        // validate SRC selector
        TrafficSelector.Builder selectorBuilder1 = DefaultTrafficSelector.builder();
        selectorBuilder1.matchInPort(d1p3.port());
        selectorBuilder1.add(Criteria.matchOduSignalType(OduSignalType.ODU2));
        assertThat(rule1.selector(), is(selectorBuilder1.build()));

        // validate SRC treatment  (without OduSignalId - all TributarySlots are used)
        TrafficTreatment.Builder treatmentBuilder1 = DefaultTrafficTreatment.builder();
        treatmentBuilder1.setOutput(d1p2.port());
        assertThat(rule1.treatment(), is(treatmentBuilder1.build()));

        // 2nd Device
        FlowRule rule2 = rules.stream()
                .filter(x -> x.deviceId().equals(device2.id()))
                .findFirst()
                .get();
        // validate SRC selector
        TrafficSelector.Builder selectorBuilder2 = DefaultTrafficSelector.builder();
        selectorBuilder2.matchInPort(d2p1.port());
        selectorBuilder2.add(Criteria.matchOduSignalType(OduSignalType.ODU2));
        assertThat(rule2.selector(), is(selectorBuilder2.build()));

        // validate SRC treatment  (without OduSignalId - all TributarySlots are used)
        TrafficTreatment.Builder treatmentBuilder2 = DefaultTrafficTreatment.builder();
        treatmentBuilder2.setOutput(d2p2.port());
        assertThat(rule2.treatment(), is(treatmentBuilder2.build()));


        // 3rd Device
        FlowRule rule3 = rules.stream()
                .filter(x -> x.deviceId().equals(device3.id()))
                .findFirst()
                .get();
        // validate DST selector (without OduSignalId - all TributarySlots are used)
        TrafficSelector.Builder selectorBuilder3 = DefaultTrafficSelector.builder();
        selectorBuilder3.matchInPort(d3p1.port());
        selectorBuilder3.add(Criteria.matchOduSignalType(OduSignalType.ODU2));
        assertThat(rule3.selector(), is(selectorBuilder3.build()));

        // validate DST treatment
        assertThat(rule3.treatment(), is(
                DefaultTrafficTreatment.builder().setOutput(d3p3.port()).build()
                ));

        rules.forEach(rule -> assertEquals("FlowRule priority is incorrect",
                intent.priority(), rule.priority()));

        sut.deactivate();
    }

}