/*
 * Copyright 2016 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.DriverData;
import org.onosproject.net.driver.DriverHandler;
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 org.onosproject.openflow.DriverAdapter;
import org.onosproject.openflow.DriverServiceAdapter;

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