/*
 * 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.mapping.web;

import com.eclipsesource.json.Json;
import com.eclipsesource.json.JsonArray;
import com.eclipsesource.json.JsonObject;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.glassfish.jersey.server.ResourceConfig;
import org.hamcrest.Description;
import org.hamcrest.TypeSafeMatcher;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.osgi.TestServiceDirectory;
import org.onlab.packet.IpPrefix;
import org.onlab.rest.BaseResource;
import org.onosproject.codec.CodecService;
import org.onosproject.codec.impl.CodecManager;
import org.onosproject.mapping.DefaultMappingKey;
import org.onosproject.mapping.DefaultMappingTreatment;
import org.onosproject.mapping.DefaultMappingValue;
import org.onosproject.mapping.MappingEntry;
import org.onosproject.mapping.MappingId;
import org.onosproject.mapping.MappingKey;
import org.onosproject.mapping.MappingService;
import org.onosproject.mapping.MappingTreatment;
import org.onosproject.mapping.MappingValue;
import org.onosproject.mapping.actions.MappingAction;
import org.onosproject.mapping.actions.MappingActions;
import org.onosproject.mapping.addresses.MappingAddress;
import org.onosproject.mapping.addresses.MappingAddresses;
import org.onosproject.mapping.codec.MappingActionCodec;
import org.onosproject.mapping.codec.MappingAddressCodec;
import org.onosproject.mapping.codec.MappingEntryCodec;
import org.onosproject.mapping.codec.MappingInstructionCodec;
import org.onosproject.mapping.codec.MappingKeyCodec;
import org.onosproject.mapping.codec.MappingTreatmentCodec;
import org.onosproject.mapping.codec.MappingValueCodec;
import org.onosproject.mapping.instructions.MappingInstruction;
import org.onosproject.mapping.web.api.MappingsWebApplication;
import org.onosproject.net.DefaultDevice;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.device.DeviceService;
import org.onosproject.rest.resources.ResourceTest;

import javax.ws.rs.client.WebTarget;
import java.util.Map;
import java.util.Set;

import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.onosproject.mapping.MappingStore.Type.MAP_DATABASE;
import static org.onosproject.mapping.instructions.MappingInstructions.multicastPriority;
import static org.onosproject.mapping.instructions.MappingInstructions.multicastWeight;
import static org.onosproject.mapping.instructions.MappingInstructions.unicastPriority;
import static org.onosproject.mapping.instructions.MappingInstructions.unicastWeight;

/**
 * Unit tests for Mappings REST APIs.
 */
public class MappingsWebResourceTest extends ResourceTest {

    private static final String IPV4_STRING_1 = "1.2.3.4";
    private static final String IPV4_STRING_2 = "5.6.7.8";
    private static final String PORT_STRING = "32";
    private static final IpPrefix IPV4_PREFIX_1 =
            IpPrefix.valueOf(IPV4_STRING_1 + "/" + PORT_STRING);
    private static final IpPrefix IPV4_PREFIX_2 =
            IpPrefix.valueOf(IPV4_STRING_2 + "/" + PORT_STRING);

    private static final int UNICAST_WEIGHT = 1;
    private static final int UNICAST_PRIORITY = 1;
    private static final int MULTICAST_WEIGHT = 2;
    private static final int MULTICAST_PRIORITY = 2;

    private static final int DIFF_VALUE = 99;

    private static final String ID = "id";
    private static final String DATABASE = "database";

    private static final String PREFIX = "mappings";

    private final MappingService mockMappingService = createMock(MappingService.class);

    private final Map<DeviceId, Set<MappingEntry>> mappings = Maps.newHashMap();

    private final DeviceService mockDeviceService = createMock(DeviceService.class);
    private final DeviceId deviceId1 = DeviceId.deviceId("1");
    private final DeviceId deviceId2 = DeviceId.deviceId("2");
    private final Device device1 = new DefaultDevice(null, deviceId1, Device.Type.ROUTER,
            "", "", "", "", null);
    private final Device device2 = new DefaultDevice(null, deviceId2, Device.Type.ROUTER,
            "", "", "", "", null);

    private final MockMappingEntry mapping1 = new MockMappingEntry(deviceId1, 1);
    private final MockMappingEntry mapping2 = new MockMappingEntry(deviceId1, 2);

    private final MockMappingEntry mapping3 = new MockMappingEntry(deviceId2, 3);
    private final MockMappingEntry mapping4 = new MockMappingEntry(deviceId2, 4);

    private final Set<MappingEntry> mappingEntries = ImmutableSet.of(mapping1, mapping2, mapping3, mapping4);

    /**
     * Constructs a mappings web resource test instance.
     */
    public MappingsWebResourceTest() {
        super(ResourceConfig.forApplicationClass(MappingsWebApplication.class));
    }

    /**
     * Mock class for a mapping entry.
     */
    private static class MockMappingEntry implements MappingEntry {
        static final short UNIQUE_SHORT = 2;
        final DeviceId deviceId;
        MappingKey key;
        MappingValue value;
        final long baseValue;

        MockMappingEntry(DeviceId deviceId, long id) {
            this.deviceId = deviceId;
            this.baseValue = id * 100;
        }

        @Override
        public MappingId id() {
            final long id = baseValue + 11;
            return MappingId.valueOf(id);
        }

        @Override
        public short appId() {
            return UNIQUE_SHORT;
        }

        @Override
        public DeviceId deviceId() {
            return deviceId;
        }

        @Override
        public MappingKey key() {
            return key;
        }

        @Override
        public MappingValue value() {
            return value;
        }

        @Override
        public MappingEntryState state() {
            return MappingEntryState.ADDED;
        }
    }

    /**
     * Populates some mappings used as testing data.
     */
    private void setupMockMappings() {
        MappingAddress address1 = MappingAddresses.ipv4MappingAddress(IPV4_PREFIX_1);
        MappingAddress address2 = MappingAddresses.ipv4MappingAddress(IPV4_PREFIX_2);

        MappingInstruction unicastWeight1 = unicastWeight(UNICAST_WEIGHT);
        MappingInstruction unicastPriority1 = unicastPriority(UNICAST_PRIORITY);
        MappingInstruction multicastWeight1 = multicastWeight(MULTICAST_WEIGHT);
        MappingInstruction multicastPriority1 = multicastPriority(MULTICAST_PRIORITY);

        MappingInstruction unicastWeight2 = unicastWeight(UNICAST_WEIGHT + DIFF_VALUE);
        MappingInstruction unicastPriority2 = unicastPriority(UNICAST_PRIORITY + DIFF_VALUE);
        MappingInstruction multicastWeight2 = multicastWeight(MULTICAST_WEIGHT + DIFF_VALUE);
        MappingInstruction multicastPriority2 = multicastPriority(MULTICAST_PRIORITY + DIFF_VALUE);

        MappingKey key1 = DefaultMappingKey.builder()
                .withAddress(address1)
                .build();

        MappingTreatment treatment1 = DefaultMappingTreatment.builder()
                .add(unicastWeight1)
                .add(unicastPriority1)
                .add(multicastWeight1)
                .add(multicastPriority1)
                .withAddress(address1)
                .build();

        MappingAction action1 = MappingActions.noAction();

        MappingValue value1 = DefaultMappingValue.builder()
                .add(treatment1)
                .withAction(action1)
                .build();

        MappingKey key2 = DefaultMappingKey.builder()
                .withAddress(address2)
                .build();

        MappingTreatment treatment2 = DefaultMappingTreatment.builder()
                .add(unicastWeight2)
                .add(unicastPriority2)
                .add(multicastWeight2)
                .add(multicastPriority2)
                .withAddress(address2)
                .build();

        MappingAction action2 = MappingActions.forward();

        MappingValue value2 = DefaultMappingValue.builder()
                .add(treatment2)
                .withAction(action2)
                .build();

        mapping1.key = key1;
        mapping2.key = key2;
        mapping3.key = key1;
        mapping4.key = key2;

        mapping1.value = value1;
        mapping2.value = value2;
        mapping3.value = value1;
        mapping4.value = value2;

        final Set<MappingEntry> mappings1 = Sets.newHashSet();
        mappings1.add(mapping1);
        mappings1.add(mapping2);

        final Set<MappingEntry> mappings2 = Sets.newHashSet();
        mappings2.add(mapping3);
        mappings2.add(mapping4);

        mappings.put(deviceId1, mappings1);
        mappings.put(deviceId2, mappings2);
    }

    /**
     * Sets up the global values for all the tests.
     */
    @Before
    public void setUpTest() {

        // Register the services needed for the test
        final CodecManager codecService = new CodecManager();
        codecService.activate();
        codecService.registerCodec(MappingEntry.class, new MappingEntryCodec());
        codecService.registerCodec(MappingAddress.class, new MappingAddressCodec());
        codecService.registerCodec(MappingInstruction.class, new MappingInstructionCodec());
        codecService.registerCodec(MappingAction.class, new MappingActionCodec());
        codecService.registerCodec(MappingTreatment.class, new MappingTreatmentCodec());
        codecService.registerCodec(MappingKey.class, new MappingKeyCodec());
        codecService.registerCodec(MappingValue.class, new MappingValueCodec());
        ServiceDirectory testDirectory =
                new TestServiceDirectory()
                        .add(MappingService.class, mockMappingService)
                        .add(DeviceService.class, mockDeviceService)
                        .add(CodecService.class, codecService);

        BaseResource.setServiceDirectory(testDirectory);
    }

    /**
     * Cleans up and verifies the mocks.
     */
    @After
    public void tearDownTest() {
        verify(mockMappingService);
    }

    public static class MappingEntryJsonArrayMatcher extends TypeSafeMatcher<JsonArray> {

        private final MappingEntry mapping;
        private String reason = "";

        MappingEntryJsonArrayMatcher(MappingEntry mappingValue) {
            mapping = mappingValue;
        }

        @Override
        protected boolean matchesSafely(JsonArray json) {

            boolean mappingFound = false;

            for (int jsonMappingIndex = 0; jsonMappingIndex < json.size();
                 jsonMappingIndex++) {

                final JsonObject jsonMapping = json.get(jsonMappingIndex).asObject();

                final String mappingId = Long.toString(mapping.id().value());
                final String jsonMappingId = jsonMapping.get(ID).asString();
                if (jsonMappingId.equals(mappingId)) {
                    mappingFound = true;
                    assertThat(jsonMapping, matchesMapping(mapping));
                }
            }

            if (!mappingFound) {
                reason = "Mapping with id " + mapping.id().toString() + " not found";
                return false;
            } else {
                return true;
            }
        }

        @Override
        public void describeTo(Description description) {
            description.appendText(reason);
        }
    }

    /**
     * Hamcrest matcher for mapping entry.
     */
    public static final class MappingEntryJsonMatcher
            extends TypeSafeMatcher<JsonObject> {

        private final MappingEntry mappingEntry;
        private String reason = "";

        /**
         * A default constructor.
         *
         * @param mappingEntry mapping entry
         */
        private MappingEntryJsonMatcher(MappingEntry mappingEntry) {
            this.mappingEntry = mappingEntry;
        }

        @Override
        protected boolean matchesSafely(JsonObject jsonObject) {
            // check mapping id
            final String jsonId = jsonObject.get("id").asString();
            final String mappingId = Long.toString(mappingEntry.id().value());

            if (!jsonId.equals(mappingId)) {
                reason = "id " + mappingEntry.id().toString();
                return false;
            }

            // check device id
            final String jsonDeviceId = jsonObject.get("deviceId").asString();
            final String deviceId = mappingEntry.deviceId().toString();
            if (!jsonDeviceId.equals(deviceId)) {
                reason = "deviceId " + mappingEntry.deviceId();
                return false;
            }

            // check state
            final String jsonState = jsonObject.get("state").asString();
            final String state = mappingEntry.state().name();
            if (!jsonState.equals(state)) {
                reason = "state " + mappingEntry.state().name();
                return false;
            }

            return true;
        }

        @Override
        public void describeTo(Description description) {
            description.appendText(reason);
        }
    }

    /**
     * Factory to allocate a mapping matcher.
     *
     * @param mapping mapping object we are looking for
     * @return matcher
     */
    private static MappingEntryJsonMatcher matchesMapping(MappingEntry mapping) {
        return new MappingEntryJsonMatcher(mapping);
    }

    /**
     * Factory to allocate a mapping array matcher.
     *
     * @param mapping mapping object we are looking for
     * @return matcher
     */
    private static MappingEntryJsonArrayMatcher hasMapping(MappingEntry mapping) {
        return new MappingEntryJsonArrayMatcher(mapping);
    }

    /**
     * Tests the result of the rest api GET when there are no mappings.
     */
    @Test
    public void testMappingsEmptyArray() {
        expect(mockMappingService.getAllMappingEntries(anyObject()))
                .andReturn(null).anyTimes();
        replay(mockMappingService);
        final WebTarget wt = target();
        final String response = wt.path(PREFIX + "/" + DATABASE).request().get(String.class);
        assertThat(response, is("{\"mappings\":[]}"));
    }

    /**
     * Tests the result of the rest api GET when there are active mappings.
     */
    @Test
    public void testMappingsPopulateArray() {
        setupMockMappings();
        expect(mockMappingService.getAllMappingEntries(anyObject()))
                .andReturn(mappingEntries).once();
        replay(mockMappingService);
        final WebTarget wt = target();
        final String response = wt.path(PREFIX + "/" + DATABASE).request().get(String.class);
        final JsonObject result = Json.parse(response).asObject();
        assertThat(result, notNullValue());

        assertThat(result.names(), hasSize(1));
        assertThat(result.names().get(0), is("mappings"));
        final JsonArray jsonMappings = result.get("mappings").asArray();
        assertThat(jsonMappings, notNullValue());
        assertThat(jsonMappings, hasMapping(mapping1));
        assertThat(jsonMappings, hasMapping(mapping2));
        assertThat(jsonMappings, hasMapping(mapping3));
        assertThat(jsonMappings, hasMapping(mapping4));
    }

    /**
     * Tests the result of the rest api GET with a device ID when there are
     * no mappings.
     */
    @Test
    public void testMappingsByDevIdEmptyArray() {
        expect(mockDeviceService.getDevice(deviceId1)).andReturn(device1);
        expect(mockMappingService.getMappingEntries(MAP_DATABASE, deviceId1))
                .andReturn(null).anyTimes();
        replay(mockDeviceService);
        replay(mockMappingService);

        final WebTarget wt = target();
        final String response = wt.path(PREFIX + "/" + deviceId1 + "/" + DATABASE)
                .request().get(String.class);
        assertThat(response, is("{\"mappings\":[]}"));
    }

    /**
     * Tests the result of the rest api GET with a device ID when there are
     * active mappings.
     */
    @Test
    public void testMappingsByDevIdPopulateArray() {
        setupMockMappings();
        expect(mockDeviceService.getDevice(deviceId2)).andReturn(device2);
        expect(mockMappingService.getMappingEntries(MAP_DATABASE, deviceId2))
                .andReturn(mappings.get(deviceId2)).once();
        replay(mockDeviceService);
        replay(mockMappingService);

        final WebTarget wt = target();
        final String response = wt.path(PREFIX + "/" + deviceId2 + "/" + DATABASE)
                .request().get(String.class);

        final JsonObject result = Json.parse(response).asObject();
        assertThat(result, notNullValue());

        assertThat(result.names(), hasSize(1));
        assertThat(result.names().get(0), is("mappings"));
        final JsonArray jsonMappings = result.get("mappings").asArray();
        assertThat(jsonMappings, notNullValue());
        assertThat(jsonMappings, hasMapping(mapping3));
        assertThat(jsonMappings, hasMapping(mapping4));
    }
}
