/*
 * Copyright 2017-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.store.meter.impl;

import com.google.common.collect.Lists;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.junit.TestUtils;
import org.onlab.packet.IpAddress;
import org.onlab.util.KryoNamespace;
import org.onosproject.TestApplicationId;
import org.onosproject.cluster.NodeId;
import org.onosproject.net.DeviceId;
import org.onosproject.net.behaviour.MeterQuery;
import org.onosproject.net.driver.Behaviour;
import org.onosproject.net.driver.Driver;
import org.onosproject.net.driver.DriverData;
import org.onosproject.net.driver.DriverHandler;
import org.onosproject.net.driver.DriverServiceAdapter;
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.Meter;
import org.onosproject.net.meter.MeterFeatures;
import org.onosproject.net.meter.MeterFeaturesKey;
import org.onosproject.net.meter.MeterId;
import org.onosproject.net.meter.MeterKey;
import org.onosproject.net.meter.MeterState;
import org.onosproject.store.service.Serializer;
import org.onosproject.store.service.TestStorageService;

import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

import static org.hamcrest.Matchers.is;
import static org.junit.Assert.*;
import static org.onosproject.net.NetTestTools.APP_ID;
import static org.onosproject.net.NetTestTools.did;

/**
 * Meter store tests.
 */
public class DistributedMeterStoreTest {

    // 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");

    // Store under testing
    private DistributedMeterStore meterStore;

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

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

    // Bands used during the tests
    private 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();

    // 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
        meterStore = new DistributedMeterStore();
        // Let's initialize some internal services
        TestUtils.setField(meterStore, "storageService", new TestStorageService());
        TestUtils.setField(meterStore, "driverService", new TestDriverService());

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

    @After
    public void tearDown() {
        // Deactivate the 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);
    }

    /**
     * Test proper store of meter features.
     */
    @Test
    public void testStoreMeterFeatures() {
        // Let's store feature for device 1
        meterStore.storeMeterFeatures(mef1);
        // Verify store meter features
        assertThat(meterStore.getMaxMeters(MeterFeaturesKey.key(did1)), is(3L));
        // Let's store feature for device 1
        meterStore.storeMeterFeatures(mef2);
        // Verify store meter features
        assertThat(meterStore.getMaxMeters(MeterFeaturesKey.key(did2)), is(10L));
    }

    /**
     * Test proper delete of meter features.
     */
    @Test
    public void testDeleteMeterFeatures() {
        // Let's store feature for device 1
        meterStore.storeMeterFeatures(mef1);
        // Verify store meter features
        assertThat(meterStore.getMaxMeters(MeterFeaturesKey.key(did1)), is(3L));
        // Let's delete the features
        meterStore.deleteMeterFeatures(did1);
        // Verify delete meter features
        assertThat(meterStore.getMaxMeters(MeterFeaturesKey.key(did1)), is(0L));
    }

    /**
     * Test proper allocation of meter ids.
     */
    @Test
    public void testAllocateId() {
        // Init the store
        initMeterStore();
        // Allocate a meter id and verify is equal to mid1
        assertThat(mid1, is(meterStore.allocateMeterId(did1)));
        // Allocate a meter id and verify is equal to mid2
        assertThat(mid2, is(meterStore.allocateMeterId(did1)));
    }

    /**
     * Test proper free of meter ids.
     */
    @Test
    public void testFreeId() {
        // Init the store
        initMeterStore();
        // Allocate a meter id and verify is equal to mid1
        assertThat(mid1, is(meterStore.allocateMeterId(did1)));
        // Free the above id
        meterStore.freeMeterId(did1, mid1);
        // Allocate a meter id and verify is equal to mid1
        assertThat(mid1, is(meterStore.allocateMeterId(did1)));
        // Free an id not allocated
        meterStore.freeMeterId(did1, mid10);
        // Allocate a meter id and verify is equal to mid2
        assertThat(mid2, is(meterStore.allocateMeterId(did1)));
    }

    /**
     * Test proper reuse of meter ids.
     */
    @Test
    public void testReuseId() {
        // Init the store
        initMeterStore();
        // Reserve id 1
        MeterId meterIdOne = meterStore.allocateMeterId(did2);
        // Free the above id
        meterStore.freeMeterId(did2, meterIdOne);
        // Start an async reservation
        CompletableFuture<MeterId> future = CompletableFuture.supplyAsync(
                () -> meterStore.allocateMeterId(did2)
        );
        // Start another reservation
        MeterId meterIdTwo = meterStore.allocateMeterId(did2);
        try {
            meterIdOne = future.get();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
        // Ids should be different, otherwise we had clash in the store
        assertNotEquals("Ids should be different", meterIdOne, meterIdTwo);

        // Free the above id
        meterStore.freeMeterId(did1, meterIdOne);
        // Free the above id
        meterStore.freeMeterId(did1, meterIdTwo);
        // Reserve id 1
        meterIdOne = meterStore.allocateMeterId(did2);
        // Reserve id 2
        meterStore.allocateMeterId(did2);
        // Reserve id 3
        MeterId meterIdThree = meterStore.allocateMeterId(did2);
        // Reserve id 4
        MeterId meterIdFour = meterStore.allocateMeterId(did2);
        // Free the above id
        meterStore.freeMeterId(did1, meterIdOne);
        // Free the above id
        meterStore.freeMeterId(did1, meterIdThree);
        // Free the above id
        meterStore.freeMeterId(did1, meterIdFour);
        // Start an async reservation
        future = CompletableFuture.supplyAsync(
                () -> meterStore.allocateMeterId(did2)
        );
        // Start another reservation
        MeterId meterAnotherId = meterStore.allocateMeterId(did2);
        try {
            meterAnotherId = future.get();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
        // Ids should be different, otherwise we had clash in the store
        assertNotEquals("Ids should be different", meterAnotherId, meterIdOne);
    }

    /**
     * Test query meters mechanism.
     */
    @Test
    public void testQueryMeters() {
        // Init the store
        initMeterStore();
        // Let's test queryMeters
        assertThat(mid1, is(meterStore.allocateMeterId(did3)));
        // Let's test queryMeters error
        assertNull(meterStore.allocateMeterId(did4));
    }

    /**
     * Test max meter error.
     */
    @Test
    public void testMaxMeterError() {
        // Init the store
        initMeterStore();
        // Reserve id 1
        assertThat(mid1, is(meterStore.allocateMeterId(did1)));
        // Reserve id 2
        assertThat(mid2, is(meterStore.allocateMeterId(did1)));
        // Max meter error
        assertNull(meterStore.allocateMeterId(did1));
    }

    /**
     * Test store meter.
     */
    @Test
    public void testStoreMeter() {
        // Init the store
        initMeterStore();
        // Simulate the allocation of an id
        MeterId idOne = meterStore.allocateMeterId(did1);
        // Verify the allocation
        assertThat(mid1, is(idOne));
        // Let's create a meter
        Meter meterOne = DefaultMeter.builder()
                .forDevice(did1)
                .fromApp(APP_ID)
                .withId(mid1)
                .withUnit(Meter.Unit.KB_PER_SEC)
                .withBands(Collections.singletonList(b1))
                .build();
        // Set the state
        ((DefaultMeter) meterOne).setState(MeterState.PENDING_ADD);
        // Store the meter
        meterStore.storeMeter(meterOne);
        // Let's create meter key
        MeterKey meterKey = MeterKey.key(did1, mid1);
        // Verify the store
        assertThat(1, is(meterStore.getAllMeters().size()));
        assertThat(1, is(meterStore.getAllMeters(did1).size()));
        assertThat(m1, is(meterStore.getMeter(meterKey)));
    }

    /**
     * Test delete meter.
     */
    @Test
    public void testDeleteMeter() {
        // Init the store
        initMeterStore();
        // Simulate the allocation of an id
        MeterId idOne = meterStore.allocateMeterId(did1);
        // Verify the allocation
        assertThat(mid1, is(idOne));
        // Let's create a meter
        Meter meterOne = DefaultMeter.builder()
                .forDevice(did1)
                .fromApp(APP_ID)
                .withId(mid1)
                .withUnit(Meter.Unit.KB_PER_SEC)
                .withBands(Collections.singletonList(b1))
                .build();
        // Set the state
        ((DefaultMeter) meterOne).setState(MeterState.PENDING_ADD);
        // Store the meter
        meterStore.storeMeter(meterOne);
        // Set the state
        ((DefaultMeter) meterOne).setState(MeterState.PENDING_REMOVE);
        // Let's create meter key
        MeterKey meterKey = MeterKey.key(did1, mid1);
        // Delete meter
        meterStore.deleteMeter(meterOne);
        // Start an async delete, simulating the operation of the provider
        CompletableFuture<Void> future = CompletableFuture.runAsync(
                () -> meterStore.deleteMeterNow(meterOne)
        );
        // Let's wait
        try {
            future.get();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
        // Verify delete
        assertThat(0, is(meterStore.getAllMeters().size()));
        assertThat(0, is(meterStore.getAllMeters(did1).size()));
        assertNull(meterStore.getMeter(meterKey));
        assertThat(mid1, is(meterStore.allocateMeterId(did1)));
    }

    /**
     * Test no delete meter.
     */
    @Test
    public void testNoDeleteMeter() {
        // Init the store
        initMeterStore();
        // Simulate the allocation of an id
        MeterId idOne = meterStore.allocateMeterId(did1);
        // Create the key
        MeterKey keyOne = MeterKey.key(did1, idOne);
        // Let's create a meter
        Meter meterOne = DefaultMeter.builder()
                .forDevice(did1)
                .fromApp(APP_ID)
                .withId(mid1)
                .withUnit(Meter.Unit.KB_PER_SEC)
                .withBands(Collections.singletonList(b1))
                .build();
        // Set the state
        ((DefaultMeter) meterOne).setState(MeterState.PENDING_REMOVE);
        // Delete meter
        meterStore.deleteMeter(meterOne);
        // Verify No delete
        assertThat(0, is(meterStore.getAllMeters().size()));
        assertThat(0, is(meterStore.getAllMeters(did1).size()));
        assertNull(meterStore.getMeter(keyOne));
    }

    /**
     * Test purge meter.
     */
    @Test
    public void testPurgeMeter() {
        // add the meter
        testStoreMeter();
        meterStore.purgeMeter(did1);
        // Verify delete
        MeterKey keyOne = MeterKey.key(did1, mid1);
        assertThat(0, is(meterStore.getAllMeters().size()));
        assertThat(0, is(meterStore.getAllMeters(did1).size()));
        assertNull(meterStore.getMeter(keyOne));
    }

    /**
     * Test getMeters API immutability.
     */
    @Test
    public void testGetMetersImmutability() {
        // Init the store
        initMeterStore();

        // Simulate the allocation of an id
        MeterId idOne = meterStore.allocateMeterId(did1);
        // Verify the allocation
        assertThat(mid1, is(idOne));
        // Let's create a meter
        Meter meterOne = DefaultMeter.builder()
                .forDevice(did1)
                .fromApp(APP_ID)
                .withId(mid1)
                .withUnit(Meter.Unit.KB_PER_SEC)
                .withBands(Collections.singletonList(b1))
                .build();
        // Set the state
        ((DefaultMeter) meterOne).setState(MeterState.PENDING_ADD);
        // Store the meter
        meterStore.storeMeter(meterOne);

        // Verify the immutability
        Collection<Meter> meters = meterStore.getAllMeters();
        Collection<Meter> metersDevice = meterStore.getAllMeters(did1);
        assertThat(1, is(meters.size()));
        assertThat(1, is(metersDevice.size()));

        MeterId idTwo = meterStore.allocateMeterId(did1);
        // Verify the allocation
        assertThat(mid2, is(idTwo));
        // Let's create a meter
        Meter meterTwo = DefaultMeter.builder()
                .forDevice(did1)
                .fromApp(APP_ID)
                .withId(mid2)
                .withUnit(Meter.Unit.KB_PER_SEC)
                .withBands(Collections.singletonList(b1))
                .build();
        // Set the state
        ((DefaultMeter) meterTwo).setState(MeterState.PENDING_ADD);
        // Store the meter
        meterStore.storeMeter(meterTwo);

        assertThat(1, is(meters.size()));
        assertThat(1, is(metersDevice.size()));

        meters = meterStore.getAllMeters();
        metersDevice = meterStore.getAllMeters(did1);
        assertThat(2, is(meters.size()));
        assertThat(2, is(metersDevice.size()));


    }

    // Test class for driver service.
    private class TestDriverService extends DriverServiceAdapter {
        @Override
        public DriverHandler createHandler(DeviceId deviceId, String... credentials) {
            return deviceId.equals(did3) ? new TestDriverHandler() : null;
        }
    }

    // Test class for driver handler.
    private class TestDriverHandler implements DriverHandler {

        @Override
        public Driver driver() {
            return null;
        }

        @Override
        public DriverData data() {
            return null;
        }

        @Override
        @SuppressWarnings("unchecked")
        public <T extends Behaviour> T behaviour(Class<T> behaviourClass) {
            return (T) new TestMeterQuery();
        }

        @Override
        public <T> T get(Class<T> serviceClass) {
            return null;
        }

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

    // Test meter query
    private class TestMeterQuery implements MeterQuery {

        @Override
        public DriverData data() {
            return null;
        }

        @Override
        public void setData(DriverData data) {

        }
        @Override
        public DriverHandler handler() {
            return null;
        }

        @Override
        public void setHandler(DriverHandler handler) {

        }

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

}
