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

import java.util.ArrayList;
import java.util.List;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.junit.TestUtils;
import org.onlab.packet.ChassisId;
import org.onosproject.mastership.MastershipEvent;
import org.onosproject.mastership.MastershipListener;
import org.onosproject.mastership.MastershipServiceAdapter;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.DefaultDevice;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.NetTestTools;
import org.onosproject.net.behaviour.DefaultNextGroup;
import org.onosproject.net.behaviour.NextGroup;
import org.onosproject.net.behaviour.PipelinerAdapter;
import org.onosproject.net.behaviour.PipelinerContext;
import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceServiceAdapter;
import org.onosproject.net.driver.AbstractDriverLoader;
import org.onosproject.net.driver.Behaviour;
import org.onosproject.net.driver.DefaultDriverData;
import org.onosproject.net.driver.DefaultDriverHandler;
import org.onosproject.net.driver.DefaultDriverProviderService;
import org.onosproject.net.driver.Driver;
import org.onosproject.net.driver.DriverAdapter;
import org.onosproject.net.driver.DriverData;
import org.onosproject.net.driver.DriverHandler;
import org.onosproject.net.driver.DriverServiceAdapter;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.Criteria;
import org.onosproject.net.flowobjective.DefaultFilteringObjective;
import org.onosproject.net.flowobjective.DefaultForwardingObjective;
import org.onosproject.net.flowobjective.DefaultNextObjective;
import org.onosproject.net.flowobjective.FilteringObjective;
import org.onosproject.net.flowobjective.FlowObjectiveStoreDelegate;
import org.onosproject.net.flowobjective.ForwardingObjective;
import org.onosproject.net.flowobjective.NextObjective;
import org.onosproject.net.flowobjective.ObjectiveEvent;
import org.onosproject.net.intent.TestTools;

import static org.hamcrest.CoreMatchers.hasItem;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.notNullValue;
import static org.onlab.junit.TestUtils.TestUtilsException;

/**
 * Tests for the flow objective manager.
 */
public class FlowObjectiveManagerTest {

    private static final int RETRY_MS = 250;
    private FlowObjectiveManager manager;
    DeviceId id1 = NetTestTools.did("d1");
    DefaultDevice d1 = new DefaultDevice(NetTestTools.PID, id1, Device.Type.SWITCH,
                                         "test", "1.0", "1.0",
                                         "abacab", new ChassisId("c"),
                                         DefaultAnnotations.EMPTY);

    DeviceId id2 = NetTestTools.did("d2");
    DefaultDevice d2 = new DefaultDevice(NetTestTools.PID, id2, Device.Type.SWITCH,
                                         "test", "1.0", "1.0",
                                         "abacab", new ChassisId("c"),
                                         DefaultAnnotations.EMPTY);

    List<String> filteringObjectives;
    List<String> forwardingObjectives;
    List<String> nextObjectives;

    private class TestDeviceService extends DeviceServiceAdapter {

        List<Device> deviceList;

        TestDeviceService() {
            deviceList = new ArrayList<>();

            deviceList.add(d1);
        }

        @Override
        public Iterable<Device> getDevices() {
            return deviceList;
        }

        @Override
        public boolean isAvailable(DeviceId deviceId) {
            return true;
        }
    }

    private class TestFlowObjectiveStore extends FlowObjectiveStoreAdapter {
        @Override
        public NextGroup getNextGroup(Integer nextId) {
            if (nextId != 4) {
                byte[] data = new byte[1];
                data[0] = 5;
                return new DefaultNextGroup(data);
            } else {
                return null;
            }
        }

    }

    private class TestDriversLoader extends AbstractDriverLoader implements DefaultDriverProviderService {
        public TestDriversLoader() {
            super("/onos-drivers.xml");
        }
    }

    private class TestDriver extends DriverAdapter {

        @Override
        public boolean hasBehaviour(Class<? extends Behaviour> behaviourClass) {
            return true;
        }

        @Override
        @SuppressWarnings("unchecked")
        public <T extends Behaviour> T createBehaviour(DriverData data, Class<T> behaviourClass) {
            return (T) new TestPipeliner();
        }

        @Override
        @SuppressWarnings("unchecked")
        public <T extends Behaviour> T createBehaviour(DriverHandler handler, Class<T> behaviourClass) {
            return (T) new TestPipeliner();
        }

    }

    private class TestPipeliner extends PipelinerAdapter {
        DeviceId deviceId;

        @Override
        public void init(DeviceId deviceId, PipelinerContext context) {
            this.deviceId = deviceId;
        }

        @Override
        public void filter(FilteringObjective filterObjective) {
            filteringObjectives.add(deviceId.toString());
        }

        @Override
        public void forward(ForwardingObjective forwardObjective) {
            forwardingObjectives.add(deviceId.toString());
        }

        @Override
        public void next(NextObjective nextObjective) {
            nextObjectives.add(deviceId.toString());
        }
    }

    private class TestDriverService extends DriverServiceAdapter {
        @Override
        public DriverHandler createHandler(DeviceId deviceId, String... credentials) {
            Driver driver = new TestDriver();
            return new DefaultDriverHandler(new DefaultDriverData(driver, id1));
        }
    }

    @Before
    public void initializeTest() {
        manager = new FlowObjectiveManager();
        manager.flowObjectiveStore = new TestFlowObjectiveStore();
        manager.mastershipService = new MastershipServiceAdapter();
        manager.deviceService = new TestDeviceService();
        manager.defaultDriverService = new TestDriversLoader();
        manager.driverService = new TestDriverService();

        filteringObjectives = new ArrayList<>();
        forwardingObjectives = new ArrayList<>();
        nextObjectives = new ArrayList<>();
        manager.activate();
    }

    @After
    public void tearDownTest() {
        manager.deactivate();
        manager = null;
        filteringObjectives.clear();
        forwardingObjectives.clear();
        nextObjectives.clear();
    }

    /**
     * Tests adding a forwarding objective.
     */
    @Test
    public void forwardingObjective() {
        TrafficSelector selector = DefaultTrafficSelector.emptySelector();
        TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
        ForwardingObjective forward =
                DefaultForwardingObjective.builder()
                        .fromApp(NetTestTools.APP_ID)
                        .withFlag(ForwardingObjective.Flag.SPECIFIC)
                        .withSelector(selector)
                        .withTreatment(treatment)
                        .makePermanent()
                        .add();

        manager.forward(id1, forward);

        TestTools.assertAfter(RETRY_MS, () ->
            assertThat(forwardingObjectives, hasSize(1)));

        assertThat(forwardingObjectives, hasItem("of:d1"));
        assertThat(filteringObjectives, hasSize(0));
        assertThat(nextObjectives, hasSize(0));
    }

    /**
     * Tests adding a filtering objective.
     */
    @Test
    public void filteringObjective() {
        TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
        FilteringObjective filter =
                DefaultFilteringObjective.builder()
                        .fromApp(NetTestTools.APP_ID)
                        .withMeta(treatment)
                        .makePermanent()
                        .deny()
                        .addCondition(Criteria.matchEthType(12))
                        .add();

        manager.activate();
        manager.filter(id1, filter);

        TestTools.assertAfter(RETRY_MS, () ->
                assertThat(filteringObjectives, hasSize(1)));

        assertThat(forwardingObjectives, hasSize(0));
        assertThat(filteringObjectives, hasItem("of:d1"));
        assertThat(nextObjectives, hasSize(0));
    }

    /**
     * Tests adding a next objective.
     */
    @Test
    public void nextObjective() {
        TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
        NextObjective next =
                DefaultNextObjective.builder()
                        .withId(manager.allocateNextId())
                        .addTreatment(treatment)
                        .withType(NextObjective.Type.BROADCAST)
                        .fromApp(NetTestTools.APP_ID)
                        .makePermanent()
                        .add();

        manager.next(id1, next);

        TestTools.assertAfter(RETRY_MS, () ->
                assertThat(nextObjectives, hasSize(1)));

        assertThat(forwardingObjectives, hasSize(0));
        assertThat(filteringObjectives, hasSize(0));
        assertThat(nextObjectives, hasItem("of:d1"));
    }

    /**
     * Tests adding a pending forwarding objective.
     *
     * @throws TestUtilsException if lookup of a field fails
     */
    @Test
    public void pendingForwardingObjective() throws TestUtilsException {
        TrafficSelector selector = DefaultTrafficSelector.emptySelector();
        TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();

        ForwardingObjective forward4 =
                DefaultForwardingObjective.builder()
                        .fromApp(NetTestTools.APP_ID)
                        .withFlag(ForwardingObjective.Flag.SPECIFIC)
                        .withSelector(selector)
                        .withTreatment(treatment)
                        .makePermanent()
                        .nextStep(4)
                        .add();
        ForwardingObjective forward5 =
                DefaultForwardingObjective.builder()
                        .fromApp(NetTestTools.APP_ID)
                        .withFlag(ForwardingObjective.Flag.SPECIFIC)
                        .withSelector(selector)
                        .withTreatment(treatment)
                        .makePermanent()
                        .nextStep(5)
                        .add();

        //  multiple pending forwards should be combined
        manager.forward(id1, forward4);
        manager.forward(id1, forward4);
        manager.forward(id1, forward5);


        //  1 should be complete, 1 pending
        TestTools.assertAfter(RETRY_MS, () ->
                assertThat(forwardingObjectives, hasSize(1)));

        assertThat(forwardingObjectives, hasItem("of:d1"));
        assertThat(filteringObjectives, hasSize(0));
        assertThat(nextObjectives, hasSize(0));

        // Now send events to trigger the objective still in the queue
        ObjectiveEvent event1 = new ObjectiveEvent(ObjectiveEvent.Type.ADD, 4);
        FlowObjectiveStoreDelegate delegate = TestUtils.getField(manager, "delegate");
        delegate.notify(event1);

        // all should be processed now
        TestTools.assertAfter(RETRY_MS, () ->
                assertThat(forwardingObjectives, hasSize(2)));
        assertThat(forwardingObjectives, hasItem("of:d1"));
        assertThat(filteringObjectives, hasSize(0));
        assertThat(nextObjectives, hasSize(0));
    }

    /**
     * Tests receipt of a device up event.
     *
     * @throws TestUtilsException if lookup of a field fails
     */
    @Test
    public void deviceUpEvent() throws TestUtilsException {
        TrafficSelector selector = DefaultTrafficSelector.emptySelector();
        TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();

        DeviceEvent event = new DeviceEvent(DeviceEvent.Type.DEVICE_ADDED, d2);
        DeviceListener listener = TestUtils.getField(manager, "deviceListener");
        assertThat(listener, notNullValue());

        listener.event(event);

        ForwardingObjective forward =
                DefaultForwardingObjective.builder()
                        .fromApp(NetTestTools.APP_ID)
                        .withFlag(ForwardingObjective.Flag.SPECIFIC)
                        .withSelector(selector)
                        .withTreatment(treatment)
                        .makePermanent()
                        .add();
        manager.forward(id2, forward);

        // new device should have an objective now
        TestTools.assertAfter(RETRY_MS, () ->
                assertThat(forwardingObjectives, hasSize(1)));

        assertThat(forwardingObjectives, hasItem("of:d2"));
        assertThat(filteringObjectives, hasSize(0));
        assertThat(nextObjectives, hasSize(0));
    }

    /**
     * Tests recepit of a device mastership event.
     *
     * @throws TestUtilsException if lookup of a field fails
     */
    @Test
    public void deviceMastershipEvent() throws TestUtilsException {
        TrafficSelector selector = DefaultTrafficSelector.emptySelector();
        TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();

        MastershipEvent event =
                new MastershipEvent(MastershipEvent.Type.MASTER_CHANGED, id2, null);
        MastershipListener listener = TestUtils.getField(manager, "mastershipListener");
        assertThat(listener, notNullValue());

        listener.event(event);

        ForwardingObjective forward =
                DefaultForwardingObjective.builder()
                        .fromApp(NetTestTools.APP_ID)
                        .withFlag(ForwardingObjective.Flag.SPECIFIC)
                        .withSelector(selector)
                        .withTreatment(treatment)
                        .makePermanent()
                        .add();
        manager.forward(id2, forward);

        // new device should have an objective now
        TestTools.assertAfter(RETRY_MS, () ->
                assertThat(forwardingObjectives, hasSize(1)));

        assertThat(forwardingObjectives, hasItem("of:d2"));
        assertThat(filteringObjectives, hasSize(0));
        assertThat(nextObjectives, hasSize(0));
    }
}
