/*
 * 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.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));
    }
}
