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

import org.easymock.EasyMock;
import org.junit.After;
import org.junit.Before;
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.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.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.OchPort;
import org.onosproject.net.OchSignal;
import org.onosproject.net.OduCltPort;
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.provider.ProviderId;
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.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 OduCltPort(device1, PortNumber.portNumber(1), true, CltSignalType.CLT_1GBE, annotations1);
    private static final OduCltPort D2P1 =
            new OduCltPort(device2, PortNumber.portNumber(1), true, CltSignalType.CLT_1GBE, annotations1);

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

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


    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 (Port) D1P1;
                    case "2":
                        return (Port) D1P2;
                    case "3":
                        return (Port) D1P3;
                    default:
                        return null;
                }
            }
            if (deviceId.equals(deviceId(DEV2))) {
                switch (portNumber.toString()) {
                    case "1":
                        return (Port) D2P1;
                    case "2":
                        return (Port) D2P2;
                    case "3":
                        return (Port) 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;
        }
    }

    @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();
    }

}
