/*
 * Copyright 2016-present Open Networking Laboratory
 *
 * 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 org.easymock.EasyMock;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.onlab.packet.ChassisId;
import org.onosproject.TestApplicationId;
import org.onosproject.cfg.ComponentConfigService;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.core.IdGenerator;
import org.onosproject.net.AbstractProjectableModel;
import org.onosproject.net.Annotations;
import org.onosproject.net.ChannelSpacing;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.CltSignalType;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultDevice;
import org.onosproject.net.DefaultPort;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.OchSignal;
import org.onosproject.net.OduSignalId;
import org.onosproject.net.OduSignalType;
import org.onosproject.net.OduSignalUtils;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.TributarySlot;
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.FlowRuleIntent;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentExtensionService;
import org.onosproject.net.intent.IntentId;
import org.onosproject.net.intent.IntentServiceAdapter;
import org.onosproject.net.intent.Key;
import org.onosproject.net.intent.MockIdGenerator;
import org.onosproject.net.intent.OpticalCircuitIntent;
import org.onosproject.net.optical.OchPort;
import org.onosproject.net.optical.OduCltPort;
import org.onosproject.net.optical.impl.DefaultOchPort;
import org.onosproject.net.optical.impl.DefaultOduCltPort;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.net.resource.MockResourceService;
import org.onosproject.net.intent.IntentSetMultimap;
import org.onosproject.net.behaviour.TributarySlotQuery;
import org.onosproject.net.device.DeviceServiceAdapter;
import org.onosproject.net.driver.Behaviour;
import org.onosproject.net.driver.DefaultDriver;
import org.onosproject.net.driver.Driver;
import org.onosproject.net.driver.DriverHandler;
import org.onosproject.net.driver.DriverService;
import org.onosproject.net.driver.DriverServiceAdapter;
import org.onosproject.net.driver.TestBehaviourImpl;
import org.onosproject.net.driver.TestBehaviourTwoImpl;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.replay;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.onosproject.net.AnnotationKeys.STATIC_PORT;
import static org.onosproject.net.AnnotationKeys.PORT_NAME;
import static org.onosproject.net.Device.Type.ROADM;
import static org.onosproject.net.DeviceId.deviceId;
import static org.onosproject.net.NetTestTools.APP_ID;

public class OpticalCircuitIntentCompilerTest {

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

    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 final IdGenerator idGenerator = new MockIdGenerator();
    private OpticalCircuitIntentCompiler sut;

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

    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 D2P1 =
            new DefaultOduCltPort(new DefaultPort(device2, PortNumber.portNumber(1), true, annotations1),
                                  CltSignalType.CLT_1GBE);

    // Och ports with signalType=ODU2
    private static final OchPort D1P2 =
            new DefaultOchPort(new DefaultPort(device1, PortNumber.portNumber(2), true, annotations2),
                               OduSignalType.ODU2,
                    true, OchSignal.newDwdmSlot(ChannelSpacing.CHL_50GHZ, 1));
    private static final OchPort D2P2 =
            new DefaultOchPort(new DefaultPort(device2, PortNumber.portNumber(2), true, annotations2),
                               OduSignalType.ODU2,
                    true, OchSignal.newDwdmSlot(ChannelSpacing.CHL_50GHZ, 1));

    // 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 D2P3 =
            new DefaultOduCltPort(new DefaultPort(device2, PortNumber.portNumber(3), true, annotations1),
                                  CltSignalType.CLT_10GBE);


    private OpticalCircuitIntent intent;

    /**
     * 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, (Port) D2P3);
            }
            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;
                    case "3":
                        return D2P3;
                    default:
                        return null;
                }
            }
            return null;
        }
    }

    /**
     * Mocks the driver service so it will appear supporting TributarySlotQuery Behaviour in the test.
     */
    private static class MockDriverServiceWithTs implements DriverService {
        @Override
        public Driver getDriver(String driverName) {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public Set<Driver> getDrivers() {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public Set<Driver> getDrivers(Class<? extends Behaviour> withBehaviour) {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public Driver getDriver(String mfr, String hw, String sw) {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public Driver getDriver(DeviceId deviceId) {
            DefaultDriver ddp = new DefaultDriver("foo.base", new ArrayList<>(), "Circus", "lux", "1.2a",
                    ImmutableMap.of(Behaviour.class,
                                    TestBehaviourImpl.class,
                                    TributarySlotQuery.class,
                                    TestBehaviourTwoImpl.class),
                    ImmutableMap.of("foo", "bar"));
            return ddp;
        }

        @Override
        public DriverHandler createHandler(DeviceId deviceId,
                String... credentials) {
            // TODO Auto-generated method stub
            return null;
        }
    }

    /**
     * Mocks the driver service so it will appear not-supporting TributarySlotQuery Behaviour in the test.
     */
    private static class MockDriverServiceNoTs implements DriverService {
        @Override
        public Driver getDriver(String driverName) {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public Set<Driver> getDrivers() {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public Set<Driver> getDrivers(Class<? extends Behaviour> withBehaviour) {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public Driver getDriver(String mfr, String hw, String sw) {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public Driver getDriver(DeviceId deviceId) {
            DefaultDriver ddp = new DefaultDriver("foo.base", new ArrayList<>(), "Circus", "lux", "1.2a",
                    ImmutableMap.of(Behaviour.class,
                                    TestBehaviourImpl.class),
                    ImmutableMap.of("foo", "bar"));
            return ddp;
        }

        @Override
        public DriverHandler createHandler(DeviceId deviceId,
                String... credentials) {
            // TODO Auto-generated method stub
            return null;
        }
    }

    private static class MockIntentSetMultimap implements IntentSetMultimap {
        @Override
        public boolean allocateMapping(IntentId keyIntentId,
                IntentId valIntentId) {
            // TODO Auto-generated method stub
            return false;
        }

        @Override
        public Set<IntentId> getMapping(IntentId intentId) {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public void releaseMapping(IntentId intentId) {
            // TODO Auto-generated method stub
        }

    }

    /**
     * Represents a fake IntentService class that easily allows to store and
     * retrieve intents without implementing the IntentService logic.
     */
    private class TestIntentService extends IntentServiceAdapter {

        private Set<Intent> intents;

        public TestIntentService() {
            intents = Sets.newHashSet();
        }

        @Override
        public void submit(Intent intent) {
            intents.add(intent);
        }

        @Override
        public long getIntentCount() {
            return intents.size();
        }

        @Override
        public Iterable<Intent> getIntents() {
            return intents;
        }

        @Override
        public Intent getIntent(Key intentKey) {
            for (Intent intent : intents) {
                if (intent.key().equals(intentKey)) {
                    return intent;
                }
            }
            return null;
        }
    }

    @BeforeClass
    public static void setUpClass() {
        AbstractProjectableModel.setDriverService("key", new DriverServiceAdapter());
    }

    @Before
    public void setUp() {
        sut = new OpticalCircuitIntentCompiler();
        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.intentService = new TestIntentService();
        sut.intentSetMultimap = new MockIntentSetMultimap();

        Intent.bindIdGenerator(idGenerator);

        intentExtensionService = createMock(IntentExtensionService.class);
        intentExtensionService.registerCompiler(OpticalCircuitIntent.class, sut);
        intentExtensionService.unregisterCompiler(OpticalCircuitIntent.class);
        sut.intentManager = intentExtensionService;
        replay(coreService, intentExtensionService);

        // mocking ComponentConfigService
        ComponentConfigService mockConfigService =
                EasyMock.createMock(ComponentConfigService.class);
        expect(mockConfigService.getProperties(anyObject())).andReturn(ImmutableSet.of());
        mockConfigService.registerProperties(sut.getClass());
        expectLastCall();
        mockConfigService.unregisterProperties(sut.getClass(), false);
        expectLastCall();
        expect(mockConfigService.getProperties(anyObject())).andReturn(ImmutableSet.of());
        sut.cfgService = mockConfigService;
        replay(mockConfigService);

    }

    @After
    public void tearDown() {
        Intent.unbindIdGenerator(idGenerator);
    }

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

        // Use driver with TributarySlotQuery Behaviour
        sut.driverService = new MockDriverServiceWithTs();

        ConnectPoint oduCltSrcCP = new ConnectPoint(device1.id(), D1P1.number());
        ConnectPoint oduCltDstCP = new ConnectPoint(device2.id(), D2P1.number());
        ConnectPoint ochSrcCP = new ConnectPoint(device1.id(), D1P2.number());
        ConnectPoint ochDstCP = new ConnectPoint(device2.id(), D2P2.number());

        intent = OpticalCircuitIntent.builder()
                .appId(APP_ID)
                .key(KEY1)
                .src(oduCltSrcCP)
                .dst(oduCltDstCP)
                .signalType(D1P1.signalType())
                .bidirectional(false)
                .build();

        sut.activate(null);

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

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

        FlowRule rule1 = rules.stream()
                .filter(x -> x.deviceId().equals(device1.id()))
                .findFirst()
                .get();
        // validate SRC selector
        TrafficSelector.Builder selectorBuilder1 = DefaultTrafficSelector.builder();
        selectorBuilder1.matchInPort(oduCltSrcCP.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(D1P2.signalType(), slots);
        treatmentBuilder1.add(Instructions.modL1OduSignalId(oduSignalId));
        treatmentBuilder1.setOutput(ochSrcCP.port());
        assertThat(rule1.treatment(), is(treatmentBuilder1.build()));

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

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

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

        sut.deactivate();
    }

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

        // Use driver with TributarySlotQuery Behaviour
        sut.driverService = new MockDriverServiceWithTs();

        ConnectPoint oduCltSrcCP = new ConnectPoint(device1.id(), D1P3.number());
        ConnectPoint oduCltDstCP = new ConnectPoint(device2.id(), D2P3.number());
        ConnectPoint ochSrcCP = new ConnectPoint(device1.id(), D1P2.number());
        ConnectPoint ochDstCP = new ConnectPoint(device2.id(), D2P2.number());

        intent = OpticalCircuitIntent.builder()
                .appId(APP_ID)
                .key(KEY1)
                .src(oduCltSrcCP)
                .dst(oduCltDstCP)
                .signalType(D1P3.signalType())
                .bidirectional(false)
                .build();

        sut.activate(null);

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

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

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

        // validate SRC treatment (without OduSignalId, i.e. All TributarySlots are used)
        TrafficTreatment.Builder treatmentBuilder1 = DefaultTrafficTreatment.builder();
        treatmentBuilder1.setOutput(ochSrcCP.port());
        assertThat(rule1.treatment(), is(treatmentBuilder1.build()));

        FlowRule rule2 = rules.stream()
                .filter(x -> x.deviceId().equals(device2.id()))
                .findFirst()
                .get();
        // validate DST selector (without OduSignalId, i.e. All TributarySlots are used)
        TrafficSelector.Builder selectorBuilder2 = DefaultTrafficSelector.builder();
        selectorBuilder2.matchInPort(ochDstCP.port());
        selectorBuilder2.add(Criteria.matchOduSignalType(OduSignalType.ODU2));
        assertThat(rule2.selector(), is(selectorBuilder2.build()));

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

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

        sut.deactivate();
    }

    /**
     * Tests compile of OpticalCircuitIntent without allocation of TributarySlots.
     * Compile two ODUCLT ports (with CLT_10GBE), over OCH ports (with ODU2):
     *   - No TributarySlots are used
     */
    @Test
    public void test10GbeNoMuxOverOdu2() {

        // Use driver without support for TributarySlotQuery Behaviour
        sut.driverService = new MockDriverServiceNoTs();

        ConnectPoint oduCltSrcCP = new ConnectPoint(device1.id(), D1P3.number());
        ConnectPoint oduCltDstCP = new ConnectPoint(device2.id(), D2P3.number());
        ConnectPoint ochSrcCP = new ConnectPoint(device1.id(), D1P2.number());
        ConnectPoint ochDstCP = new ConnectPoint(device2.id(), D2P2.number());

        intent = OpticalCircuitIntent.builder()
                .appId(APP_ID)
                .key(KEY1)
                .src(oduCltSrcCP)
                .dst(oduCltDstCP)
                .signalType(D1P3.signalType())
                .bidirectional(false)
                .build();

        sut.activate(null);

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

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

        FlowRule rule1 = rules.stream()
                .filter(x -> x.deviceId().equals(device1.id()))
                .findFirst()
                .get();
        // validate SRC selector
        TrafficSelector.Builder selectorBuilder1 = DefaultTrafficSelector.builder();
        selectorBuilder1.matchInPort(oduCltSrcCP.port());
        assertThat(rule1.selector(), is(selectorBuilder1.build()));

        // validate SRC treatment (without OduSignalType and OduSignalId: i.e. No TributarySlots are used)
        TrafficTreatment.Builder treatmentBuilder1 = DefaultTrafficTreatment.builder();
        treatmentBuilder1.setOutput(ochSrcCP.port());
        assertThat(rule1.treatment(), is(treatmentBuilder1.build()));

        FlowRule rule2 = rules.stream()
                .filter(x -> x.deviceId().equals(device2.id()))
                .findFirst()
                .get();
        // validate DST selector (without OduSignalType and OduSignalId: i.e. No TributarySlots are used)
        TrafficSelector.Builder selectorBuilder2 = DefaultTrafficSelector.builder();
        selectorBuilder2.matchInPort(ochDstCP.port());
        assertThat(rule2.selector(), is(selectorBuilder2.build()));
        // validate DST treatment
        assertThat(rule2.treatment(), is(
                DefaultTrafficTreatment.builder().setOutput(oduCltDstCP.port()).build()
                ));

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

        sut.deactivate();
    }

}
