/*
 * Copyright 2015-present Open Networking Foundation
 *
 * 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.meter.impl;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.junit.TestTools;
import org.onlab.junit.TestUtils;
import org.onlab.packet.IpAddress;
import org.onlab.util.KryoNamespace;
import org.onosproject.TestApplicationId;
import org.onosproject.cfg.ComponentConfigAdapter;
import org.onosproject.cluster.ClusterServiceAdapter;
import org.onosproject.cluster.ControllerNode;
import org.onosproject.cluster.DefaultControllerNode;
import org.onosproject.cluster.NodeId;
import org.onosproject.common.event.impl.TestEventDispatcher;
import org.onosproject.incubator.store.meter.impl.DistributedMeterStore;
import org.onosproject.mastership.MastershipServiceAdapter;
import org.onosproject.net.AnnotationKeys;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.DefaultDevice;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.MastershipRole;
import org.onosproject.net.behaviour.MeterQuery;
import org.onosproject.net.config.NetworkConfigService;
import org.onosproject.net.config.NetworkConfigServiceAdapter;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.device.DeviceServiceAdapter;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
import org.onosproject.net.driver.DefaultDriver;
import org.onosproject.net.driver.DriverRegistry;
import org.onosproject.net.driver.impl.DriverManager;
import org.onosproject.net.driver.impl.DriverRegistryManager;
import org.onosproject.net.meter.Band;
import org.onosproject.net.meter.DefaultBand;
import org.onosproject.net.meter.DefaultMeter;
import org.onosproject.net.meter.DefaultMeterFeatures;
import org.onosproject.net.meter.DefaultMeterRequest;
import org.onosproject.net.meter.Meter;
import org.onosproject.net.meter.MeterFeatures;
import org.onosproject.net.meter.MeterId;
import org.onosproject.net.meter.MeterOperation;
import org.onosproject.net.meter.MeterOperations;
import org.onosproject.net.meter.MeterProgrammable;
import org.onosproject.net.meter.MeterProvider;
import org.onosproject.net.meter.MeterProviderRegistry;
import org.onosproject.net.meter.MeterProviderService;
import org.onosproject.net.meter.MeterRequest;
import org.onosproject.net.meter.MeterService;
import org.onosproject.net.meter.MeterState;
import org.onosproject.net.pi.PiPipeconfServiceAdapter;
import org.onosproject.net.provider.AbstractProvider;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.store.service.Serializer;
import org.onosproject.store.service.TestStorageService;

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 java.util.concurrent.CompletableFuture;

import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.onosproject.net.NetTestTools.APP_ID;
import static org.onosproject.net.NetTestTools.did;
import static org.onosproject.net.NetTestTools.injectEventDispatcher;

/**
 * Meter manager tests.
 */
public class MeterManagerTest {

    // Test node id
    private static final NodeId NID_LOCAL = new NodeId("local");

    // Test ip address
    private static final IpAddress LOCALHOST = IpAddress.valueOf("127.0.0.1");

    private static final ProviderId PID = new ProviderId("of", "foo");

    private static final ProviderId PROGRAMMABLE_PROVIDER = new ProviderId("foo", "foo");
    private static final DeviceId PROGRAMMABLE_DID = DeviceId.deviceId("test:002");

    private static final DefaultAnnotations ANNOTATIONS =
            DefaultAnnotations.builder().set(AnnotationKeys.DRIVER, "foo").build();

    private static final Device PROGRAMMABLE_DEV =
            new DefaultDevice(PROGRAMMABLE_PROVIDER, PROGRAMMABLE_DID, Device.Type.SWITCH,
                    "", "", "", "", null, ANNOTATIONS);


    private MeterService service;

    // Test Driver service used during the tests
    private DriverManager driverService;

    // Test device service used during the tests
    private DeviceService deviceService;

    // Test provider used during the tests
    private TestProvider provider;

    // Meter manager
    private MeterManager manager;

    // Meter provider registry
    private MeterProviderRegistry registry;

    // Meter provider service
    private MeterProviderService providerService;

    // Store under testing
    private DistributedMeterStore meterStore;

    // Device ids used during the tests
    private DeviceId did1 = did("1");
    private DeviceId did2 = did("2");

    // Meter ids used during the tests
    private MeterId mid1 = MeterId.meterId(1);

    // Bands used during the tests
    private static Band b1 = DefaultBand.builder()
            .ofType(Band.Type.DROP)
            .withRate(500)
            .build();

    // Meters used during the tests
    private Meter m1 = DefaultMeter.builder()
            .forDevice(did1)
            .fromApp(APP_ID)
            .withId(mid1)
            .withUnit(Meter.Unit.KB_PER_SEC)
            .withBands(Collections.singletonList(b1))
            .build();
    private Meter m2 = DefaultMeter.builder()
            .forDevice(did2)
            .fromApp(APP_ID)
            .withId(mid1)
            .withUnit(Meter.Unit.KB_PER_SEC)
            .withBands(Collections.singletonList(b1))
            .build();

    private static Meter mProgrammable = DefaultMeter.builder()
            .forDevice(PROGRAMMABLE_DID)
            .fromApp(APP_ID)
            .withId(MeterId.meterId(1))
            .withUnit(Meter.Unit.KB_PER_SEC)
            .withBands(Collections.singletonList(b1))
            .build();

    // Meter requests used during the tests
    private MeterRequest.Builder m1Request = DefaultMeterRequest.builder()
            .forDevice(did1)
            .fromApp(APP_ID)
            .withUnit(Meter.Unit.KB_PER_SEC)
            .withBands(Collections.singletonList(b1));
    private MeterRequest.Builder m2Request = DefaultMeterRequest.builder()
            .forDevice(did2)
            .fromApp(APP_ID)
            .withUnit(Meter.Unit.KB_PER_SEC)
            .withBands(Collections.singletonList(b1));

    private MeterRequest.Builder mProgrammableRequest = DefaultMeterRequest.builder()
            .forDevice(PROGRAMMABLE_DID)
            .fromApp(APP_ID)
            .withUnit(Meter.Unit.KB_PER_SEC)
            .withBands(Collections.singletonList(b1));

    // Meter features used during the tests
    private MeterFeatures mef1 = DefaultMeterFeatures.builder().forDevice(did1)
            .withMaxMeters(3L)
            .withBandTypes(new HashSet<>())
            .withUnits(new HashSet<>())
            .hasStats(false)
            .hasBurst(false)
            .withMaxBands((byte) 0)
            .withMaxColors((byte) 0)
            .build();
    private MeterFeatures mef2 = DefaultMeterFeatures.builder().forDevice(did2)
            .withMaxMeters(10L)
            .withBandTypes(new HashSet<>())
            .withUnits(new HashSet<>())
            .hasStats(false)
            .hasBurst(false)
            .withMaxBands((byte) 0)
            .withMaxColors((byte) 0)
            .build();


    @Before
    public void setup() {
        //Init step for the deviceService
        deviceService = new TestDeviceService();
        //Init step for the driver registry and driver service.
        DriverRegistryManager driverRegistry = new DriverRegistryManager();
        driverService = new TestDriverManager(driverRegistry, deviceService, new NetworkConfigServiceAdapter());
        driverRegistry.addDriver(new DefaultDriver("foo", ImmutableList.of(), "",
                "", "",
                ImmutableMap.of(MeterProgrammable.class,
                        TestMeterProgrammable.class, MeterQuery.class, TestMeterQuery.class),
                ImmutableMap.of()));

        // Init step for the store
        meterStore = new DistributedMeterStore();
        // Let's initialize some internal services of the store
        TestUtils.setField(meterStore, "storageService", new TestStorageService());
        TestUtils.setField(meterStore, "clusterService", new TestClusterService());
        TestUtils.setField(meterStore, "mastershipService", new TestMastershipService());
        TestUtils.setField(meterStore, "driverService", driverService);

        // Inject TestApplicationId into the DistributedMeterStore serializer
        KryoNamespace.Builder testKryoBuilder = TestUtils.getField(meterStore, "APP_KRYO_BUILDER");
        testKryoBuilder.register(TestApplicationId.class);
        Serializer testSerializer = Serializer.using(Lists.newArrayList(testKryoBuilder.build()));
        TestUtils.setField(meterStore, "serializer", testSerializer);

        // Activate the store
        meterStore.activate();
        // Init step for the manager
        manager = new MeterManager();
        // Let's initialize some internal services of the manager
        TestUtils.setField(manager, "store", meterStore);
        injectEventDispatcher(manager, new TestEventDispatcher());
        manager.deviceService = deviceService;
        manager.mastershipService = new TestMastershipService();
        manager.cfgService = new ComponentConfigAdapter();
        TestUtils.setField(manager, "storageService", new TestStorageService());
        // Init the reference of the registry
        registry = manager;

        manager.driverService = driverService;

        // Activate the manager
        manager.activate(null);
        // Initialize the test provider

        provider = new TestProvider(PID);
        // Register the provider against the manager
        providerService = registry.register(provider);
        // Verify register
        assertTrue("provider should be registered",
                   registry.getProviders().contains(provider.id()));
    }

    @After
    public void tearDown() {
        // Unregister provider
        registry.unregister(provider);
        // Verify unregister
        assertFalse("provider should not be registered",
                    registry.getProviders().contains(provider.id()));
        // Deactivate manager
        manager.deactivate();
        // Remove event dispatcher
        injectEventDispatcher(manager, null);
        // Deactivate store
        meterStore.deactivate();
    }

    private void initMeterStore() {
        // Let's store feature for device 1
        meterStore.storeMeterFeatures(mef1);
        // Let's store feature for device 2
        meterStore.storeMeterFeatures(mef2);
    }

    // Emulate metrics coming from the dataplane
    private void pushMetrics(MeterOperation.Type type, Meter meter) {
        // If it is an add operation
        if (type == MeterOperation.Type.ADD) {
            // Update state to added
            ((DefaultMeter) meter).setState(MeterState.ADDED);
            // Push the update in the store
            providerService.pushMeterMetrics(meter.deviceId(), Collections.singletonList(meter));
        } else {
            providerService.pushMeterMetrics(meter.deviceId(), Collections.emptyList());
        }
    }

    /**
     * Test add meter.
     */
    @Test
    public void testAdd() {
        // Init store
        initMeterStore();
        // Submit meter request
        manager.submit(m1Request.add());
        // Verify add
        assertTrue("The meter was not added", manager.getAllMeters().size() == 1);
        assertTrue("The meter was not added", manager.getMeters(did1).size() == 1);
        // Get Meter
        Meter installingMeter = manager.getMeter(did1, mid1);
        // Verify add of installingMeter and pending add state
        assertThat(installingMeter, is(m1));
        // Verify pending add state
        assertThat(installingMeter.state(), is(MeterState.PENDING_ADD));
        // Let's simulate a working data-plane
        pushMetrics(MeterOperation.Type.ADD, installingMeter);
        // Get meter
        Meter installedMeter = manager.getMeter(did1, mid1);
        // Verify installation
        assertThat(installedMeter.state(), is(MeterState.ADDED));
        assertTrue("The meter was not installed", manager.getAllMeters().size() == 1);
        assertTrue("The meter was not installed", manager.getMeters(did1).size() == 1);
    }

    /**
     * Test remove meter.
     */
    @Test
    public void testRemove() {
        // Init store
        initMeterStore();
        // Submit meter request
        manager.submit(m1Request.add());
        // Withdraw meter
        manager.withdraw(m1Request.remove(), m1.id());
        // Get Meter
        Meter withdrawingMeter = manager.getMeter(did1, mid1);
        // Verify withdrawing
        assertThat(withdrawingMeter.state(), is(MeterState.PENDING_REMOVE));
        assertTrue("The meter was not withdrawn", manager.getAllMeters().size() == 1);
        assertTrue("The meter was not withdrawn", manager.getMeters(did1).size() == 1);
        // Let's simulate a working data-plane
        pushMetrics(MeterOperation.Type.REMOVE, withdrawingMeter);
        // Verify withdrawn
        assertNull(manager.getMeter(did1, mid1));
        assertTrue("The meter was not removed", manager.getAllMeters().size() == 0);
        assertTrue("The meter was not removed", manager.getMeters(did1).size() == 0);
    }

    /**
     * Test add multiple device.
     */
    @Test
    public void testAddMultipleDevice() {
        // Init store
        initMeterStore();
        // Submit meter 1
        manager.submit(m1Request.add());
        // Submit meter 2
        manager.submit(m2Request.add());
        // Verify add
        assertTrue("The meter was not added", manager.getAllMeters().size() == 2);
        assertTrue("The meter was not added", manager.getMeters(did1).size() == 1);
        assertTrue("The meter was not added", manager.getMeters(did2).size() == 1);
        // Get Meters
        Meter installingMeter1 = manager.getMeter(did1, mid1);
        Meter installingMeter2 = manager.getMeter(did2, mid1);
        // Verify add of installingMeter
        assertThat(installingMeter1, is(m1));
        assertThat(installingMeter2, is(m2));
        // Verify pending add state
        assertThat(installingMeter1.state(), is(MeterState.PENDING_ADD));
        assertThat(installingMeter2.state(), is(MeterState.PENDING_ADD));
        // Let's simulate a working data-plane
        pushMetrics(MeterOperation.Type.ADD, installingMeter1);
        pushMetrics(MeterOperation.Type.ADD, installingMeter2);
        // Get meter
        Meter installedMeter1 = manager.getMeter(did1, mid1);
        Meter installedMeter2 = manager.getMeter(did2, mid1);
        // Verify installation
        assertThat(installedMeter1.state(), is(MeterState.ADDED));
        assertThat(installedMeter2.state(), is(MeterState.ADDED));
        assertTrue("The meter was not installed", manager.getAllMeters().size() == 2);
        assertTrue("The meter was not installed", manager.getMeters(did1).size() == 1);
        assertTrue("The meter was not installed", manager.getMeters(did2).size() == 1);
    }

    /**
     * Test remove meter.
     */
    @Test
    public void testRemoveMultipleDevice() {
        // Init store
        initMeterStore();
        // Submit meter 1
        manager.submit(m1Request.add());
        // Submit meter 2
        manager.submit(m2Request.add());
        // Withdraw meter
        manager.withdraw(m1Request.remove(), m1.id());
        // Withdraw meter
        manager.withdraw(m2Request.remove(), m2.id());
        // Get Meters
        Meter withdrawingMeter1 = manager.getMeter(did1, mid1);
        Meter withdrawingMeter2 = manager.getMeter(did2, mid1);
        // Verify withdrawing
        assertThat(withdrawingMeter1.state(), is(MeterState.PENDING_REMOVE));
        assertThat(withdrawingMeter2.state(), is(MeterState.PENDING_REMOVE));
        assertTrue("The meter was not withdrawn", manager.getAllMeters().size() == 2);
        assertTrue("The meter was not withdrawn", manager.getMeters(did1).size() == 1);
        assertTrue("The meter was not withdrawn", manager.getMeters(did2).size() == 1);
        // Let's simulate a working data-plane
        pushMetrics(MeterOperation.Type.REMOVE, withdrawingMeter1);
        pushMetrics(MeterOperation.Type.REMOVE, withdrawingMeter2);
        // Verify withdrawn
        assertNull(manager.getMeter(did1, mid1));
        assertNull(manager.getMeter(did2, mid1));
        assertTrue("The meter was not removed", manager.getAllMeters().size() == 0);
        assertTrue("The meter was not removed", manager.getMeters(did1).size() == 0);
        assertTrue("The meter was not removed", manager.getMeters(did2).size() == 0);
    }

    @Test
    public void testAddFromMeterProgrammable()  {

        // Init store
        initMeterStore();

        manager.submit(mProgrammableRequest.add());

        TestTools.assertAfter(500, () -> {

            assertTrue("The meter was not added", manager.getAllMeters().size() == 1);

            assertThat(manager.getMeter(PROGRAMMABLE_DID, MeterId.meterId(1)), is(mProgrammable));
        });

    }

    @Test
    public void testAddBatchFromMeterProgrammable()  {

        // Init store
        initMeterStore();

        List<MeterOperation> operations = ImmutableList.of(new MeterOperation(mProgrammable, MeterOperation.Type.ADD));
        manager.defaultProvider().performMeterOperation(PROGRAMMABLE_DID, new MeterOperations(operations));

        TestTools.assertAfter(500, () -> {

            assertTrue("The meter was not added", meterOperations.size() == 1);

            assertTrue("Wrong Meter Operation", meterOperations.get(0).meter().id().equals(mProgrammable.id()));
        });

    }

    @Test
    public void testGetFromMeterProgrammable()  {

        // Init store
        initMeterStore();

        MeterDriverProvider fallback = (MeterDriverProvider) manager.defaultProvider();

        testAddFromMeterProgrammable();

        fallback.init(manager.deviceService, fallback.meterProviderService, manager.mastershipService, 1);

        TestTools.assertAfter(2000, () -> {
            assertTrue("The meter was not added", manager.getAllMeters().size() == 1);
            Meter m = manager.getMeters(PROGRAMMABLE_DID).iterator().next();
            assertEquals("incorrect state", MeterState.ADDED, m.state());
        });

    }

    // Test cluster service
    private final class TestClusterService extends ClusterServiceAdapter {

        private ControllerNode local = new DefaultControllerNode(NID_LOCAL, LOCALHOST);

        @Override
        public ControllerNode getLocalNode() {
            return local;
        }

        @Override
        public Set<ControllerNode> getNodes() {
            return Sets.newHashSet();
        }

    }

    private static class TestDeviceService extends DeviceServiceAdapter {
        @Override
        public int getDeviceCount() {
            return 1;
        }

        @Override
        public Iterable<Device> getDevices() {
            return ImmutableList.of(PROGRAMMABLE_DEV);
        }

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

        @Override
        public Device getDevice(DeviceId deviceId) {
            return PROGRAMMABLE_DEV;
        }
    }

    private class TestDriverManager extends DriverManager {
        TestDriverManager(DriverRegistry registry, DeviceService deviceService,
                          NetworkConfigService networkConfigService) {
            this.registry = registry;
            this.deviceService = deviceService;
            this.networkConfigService = networkConfigService;
            this.pipeconfService = new PiPipeconfServiceAdapter();
            activate();
        }
    }

    public static class TestMeterQuery extends AbstractHandlerBehaviour
            implements MeterQuery {
        private static final long MAX_METER = 0x00000FFF;

        @Override
        public long getMaxMeters() {
            return MAX_METER;
        }
    }

    private static List<MeterOperation> meterOperations = new ArrayList<>();

    public static class TestMeterProgrammable extends AbstractHandlerBehaviour
            implements MeterProgrammable {

        @Override
        public CompletableFuture<Boolean> performMeterOperation(MeterOperation meterOp) {
            return CompletableFuture.completedFuture(meterOperations.add(meterOp));
        }

        @Override
        public CompletableFuture<Collection<Meter>> getMeters() {
            //ADD METER
            DefaultMeter mProgrammableAdded = (DefaultMeter) mProgrammable;
            mProgrammableAdded.setState(MeterState.ADDED);
            return CompletableFuture.completedFuture(ImmutableList.of(mProgrammableAdded));
        }
    }

    private class TestProvider extends AbstractProvider implements MeterProvider {

        protected TestProvider(ProviderId id) {
            super(PID);
        }

        @Override
        public void performMeterOperation(DeviceId deviceId, MeterOperations meterOps) {
            //Currently unused.
        }

        @Override
        public void performMeterOperation(DeviceId deviceId, MeterOperation meterOp) {
            //Currently unused
        }
    }

    // Test mastership service
    private final class TestMastershipService extends MastershipServiceAdapter {
        @Override
        public NodeId getMasterFor(DeviceId deviceId) {
            return NID_LOCAL;
        }

        @Override
        public MastershipRole getLocalRole(DeviceId deviceId) {
            return MastershipRole.MASTER;
        }
    }

}
