/*
 * Copyright 2016-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.rest.resources;

import com.eclipsesource.json.Json;
import com.eclipsesource.json.JsonArray;
import com.eclipsesource.json.JsonObject;
import com.google.common.collect.ImmutableSet;
import org.hamcrest.Description;
import org.hamcrest.Matchers;
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.onosproject.codec.CodecService;
import org.onosproject.codec.impl.CodecManager;
import org.onosproject.codec.impl.MeterCodec;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.core.DefaultApplicationId;
import org.onosproject.net.DefaultDevice;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.NetTestTools;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.meter.Band;
import org.onosproject.net.meter.DefaultBand;
import org.onosproject.net.meter.Meter;
import org.onosproject.net.meter.MeterCellId;
import org.onosproject.net.meter.MeterId;
import org.onosproject.net.meter.MeterService;
import org.onosproject.net.meter.MeterState;

import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.anyShort;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
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.assertEquals;
import static org.junit.Assert.assertThat;
import static org.onosproject.net.NetTestTools.APP_ID;

/**
 * Unit tests for meters REST APIs.
 */
public class MetersResourceTest extends ResourceTest {
    final MeterService mockMeterService = createMock(MeterService.class);
    CoreService mockCoreService = createMock(CoreService.class);
    final DeviceService mockDeviceService = createMock(DeviceService.class);

    final HashMap<DeviceId, Set<Meter>> meters = new HashMap<>();

    final DeviceId deviceId1 = DeviceId.deviceId("1");
    final DeviceId deviceId2 = DeviceId.deviceId("2");
    final DeviceId deviceId3 = DeviceId.deviceId("3");
    final DeviceId deviceId4 = DeviceId.deviceId("of:0000000000000001");
    final Device device1 = new DefaultDevice(null, deviceId1, Device.Type.OTHER,
            "", "", "", "", null);
    final Device device2 = new DefaultDevice(null, deviceId2, Device.Type.OTHER,
            "", "", "", "", null);
    final Device device4 = new DefaultDevice(null, deviceId4, Device.Type.OTHER,
                                             "", "", "", "", null);

    final MockMeter meter1 = new MockMeter(deviceId1, 1, 111, 1);
    final MockMeter meter2 = new MockMeter(deviceId1, 2, 222, 2);
    final MockMeter meter3 = new MockMeter(deviceId2, 3, 333, 3);
    final MockMeter meter4 = new MockMeter(deviceId2, 4, 444, 4);
    final MockMeter meter5 = new MockMeter(deviceId3, 5, 555, 5);

    /**
     * Mock class for a meter.
     */
    private static class MockMeter implements Meter {

        final DeviceId deviceId;
        final ApplicationId appId;
        final MeterId meterId;
        final long baseValue;
        final List<Band> bandList;

        public MockMeter(DeviceId deviceId, int appId, long meterId, int id) {
            this.deviceId = deviceId;
            this.appId = new DefaultApplicationId(appId, String.valueOf(appId));
            this.baseValue = id * 200L;
            this.meterId = MeterId.meterId(meterId);

            Band band = DefaultBand.builder()
                    .ofType(Band.Type.REMARK)
                    .withRate(10)
                    .dropPrecedence((short) 20)
                    .burstSize(30).build();

            this.bandList = new ArrayList<>();
            this.bandList.add(band);
        }

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

        @Override
        public MeterId id() {
            return this.meterId;
        }

        @Override
        public MeterCellId meterCellId() {
            return this.id();
        }

        @Override
        public ApplicationId appId() {
            return this.appId;
        }

        @Override
        public Unit unit() {
            return Unit.KB_PER_SEC;
        }

        @Override
        public boolean isBurst() {
            return false;
        }

        @Override
        public Collection<Band> bands() {
            return this.bandList;
        }

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

        @Override
        public long life() {
            return baseValue + 11;
        }

        @Override
        public long referenceCount() {
            return baseValue + 22;
        }

        @Override
        public long packetsSeen() {
            return baseValue + 33;
        }

        @Override
        public long bytesSeen() {
            return baseValue + 44;
        }
    }

    /**
     * Populates some meters used as testing data.
     */
    private void setupMockMeters() {
        final Set<Meter> meters1 = new HashSet<>();
        meters1.add(meter1);
        meters1.add(meter2);

        final Set<Meter> meters2 = new HashSet<>();
        meters2.add(meter3);
        meters2.add(meter4);

        meters.put(deviceId1, meters1);
        meters.put(deviceId2, meters2);

        Set<Meter> allMeters = new HashSet<>();
        for (DeviceId deviceId : meters.keySet()) {
            allMeters.addAll(meters.get(deviceId));
        }

        expect(mockMeterService.getAllMeters()).andReturn(allMeters).anyTimes();
    }

    /**
     * Sets up the global values for all the tests.
     */
    @Before
    public void setUpTest() {
        // Mock device service
        expect(mockDeviceService.getDevice(deviceId1))
                .andReturn(device1);
        expect(mockDeviceService.getDevice(deviceId2))
                .andReturn(device2);
        expect(mockDeviceService.getDevice(deviceId4))
                .andReturn(device4);
        expect(mockDeviceService.getDevices())
                .andReturn(ImmutableSet.of(device1, device2, device4));

        // Mock Core Service
        expect(mockCoreService.getAppId(anyShort()))
                .andReturn(NetTestTools.APP_ID).anyTimes();
        expect(mockCoreService.registerApplication(MeterCodec.REST_APP_ID))
                .andReturn(APP_ID).anyTimes();
        replay(mockCoreService);

        // Register the services needed for the test
        final CodecManager codecService = new CodecManager();
        codecService.activate();
        ServiceDirectory testDirectory =
                new TestServiceDirectory()
                        .add(MeterService.class, mockMeterService)
                        .add(DeviceService.class, mockDeviceService)
                        .add(CodecService.class, codecService)
                        .add(CoreService.class, mockCoreService);

        setServiceDirectory(testDirectory);
    }

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

    /**
     * Hamcrest matcher to check that a meter representation in JSON matches
     * the actual meter.
     */
    public static class MeterJsonMatcher extends TypeSafeMatcher<JsonObject> {
        private final Meter meter;
        private String reason = "";

        public MeterJsonMatcher(Meter meterValue) {
            this.meter = meterValue;
        }

        @Override
        protected boolean matchesSafely(JsonObject jsonMeter) {

            // check application id
            final String jsonAppId = jsonMeter.get("appId").asString();
            final String appId = meter.appId().name();
            if (!jsonAppId.equals(appId)) {
                reason = "appId " + meter.appId().name();
                return false;
            }

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

            // check band array
            if (meter.bands() != null) {
                final JsonArray jsonBands = jsonMeter.get("bands").asArray();
                if (meter.bands().size() != jsonBands.size()) {
                    reason = "bands array size of " +
                            Integer.toString(meter.bands().size());
                    return false;
                }
                for (final Band band : meter.bands()) {
                    boolean bandFound = false;
                    for (int bandIndex = 0; bandIndex < jsonBands.size(); bandIndex++) {
                        final String jsonType = jsonBands.get(bandIndex).asObject().get("type").asString();
                        final String bandType = band.type().name();
                        if (jsonType.equals(bandType)) {
                            bandFound = true;
                        }
                    }
                    if (!bandFound) {
                        reason = "meter band " + band.toString();
                        return false;
                    }
                }
            }

            return true;
        }

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

    private static MeterJsonMatcher matchesMeter(Meter meter) {
        return new MeterJsonMatcher(meter);
    }

    /**
     * Hamcrest matcher to check that a meter is represented properly in a JSON
     * array of meters.
     */
    public static class MeterJsonArrayMatcher extends TypeSafeMatcher<JsonArray> {
        private final Meter meter;
        private String reason = "";

        public MeterJsonArrayMatcher(Meter meterValue) {
            meter = meterValue;
        }

        @Override
        protected boolean matchesSafely(JsonArray json) {
            boolean meterFound = false;
            for (int jsonMeterIndex = 0; jsonMeterIndex < json.size(); jsonMeterIndex++) {
                final JsonObject jsonMeter = json.get(jsonMeterIndex).asObject();

                final String meterId = meter.id().toString();
                final String jsonMeterId = jsonMeter.get("id").asString();
                if (jsonMeterId.equals(meterId)) {
                    meterFound = true;

                    assertThat(jsonMeter, matchesMeter(meter));
                }
            }
            if (!meterFound) {
                reason = "Meter with id " + meter.id().toString() + " not found";
                return false;
            } else {
                return true;
            }
        }

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

    /**
     * Factory to allocate a meter array matcher.
     *
     * @param meter meter object we are looking for
     * @return matcher
     */
    private static MeterJsonArrayMatcher hasMeter(Meter meter) {
        return new MeterJsonArrayMatcher(meter);
    }

    @Test
    public void testMeterEmptyArray() {
        expect(mockMeterService.getAllMeters()).andReturn(null).anyTimes();
        replay(mockMeterService);
        replay(mockDeviceService);
        final WebTarget wt = target();
        final String response = wt.path("meters").request().get(String.class);
        assertThat(response, is("{\"meters\":[]}"));
    }

    /**
     * Tests the result of the rest api GET when there are active meters.
     */
    @Test
    public void testMetersPopulatedArray() {
        setupMockMeters();
        replay(mockMeterService);
        replay(mockDeviceService);
        final WebTarget wt = target();
        final String response = wt.path("meters").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("meters"));
        final JsonArray jsonMeters = result.get("meters").asArray();
        assertThat(jsonMeters, notNullValue());
        assertThat(jsonMeters, hasMeter(meter1));
        assertThat(jsonMeters, hasMeter(meter2));
        assertThat(jsonMeters, hasMeter(meter3));
        assertThat(jsonMeters, hasMeter(meter4));
    }

    /**
     * Tests the results of a rest api GET for a device.
     */
    @Test
    public void testMeterSingleDevice() {
        setupMockMeters();

        final Set<Meter> meters1 = new HashSet<>();
        meters1.add(meter1);
        meters1.add(meter2);

        expect(mockMeterService.getMeters(anyObject())).andReturn(meters1).anyTimes();
        replay(mockMeterService);
        replay(mockDeviceService);

        final WebTarget wt = target();
        final String response = wt.path("meters/" + deviceId1.toString()).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("meters"));
        final JsonArray jsonMeters = result.get("meters").asArray();
        assertThat(jsonMeters, notNullValue());
        assertThat(jsonMeters, hasMeter(meter1));
        assertThat(jsonMeters, hasMeter(meter2));
    }

    /**
     * Tests the result of a rest api GET for a device with meter id.
     */
    @Test
    public void testMeterSingleDeviceWithId() {
        setupMockMeters();

        expect(mockMeterService.getMeter(anyObject(), anyObject()))
                .andReturn(meter5).anyTimes();
        replay(mockMeterService);
        replay(mockDeviceService);

        final WebTarget wt = target();
        final String response = wt.path("meters/" + deviceId3.toString()
                + "/" + meter5.id().id()).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("meters"));
        final JsonArray jsonMeters = result.get("meters").asArray();
        assertThat(jsonMeters, notNullValue());
        assertThat(jsonMeters, hasMeter(meter5));
    }

    /**
     * Test whether the REST API returns 404 if no entry has been found.
     */
    @Test
    public void testMeterByDeviceIdAndMeterId() {
        setupMockMeters();

        expect(mockMeterService.getMeter(anyObject(), anyObject()))
                .andReturn(null).anyTimes();
        replay(mockMeterService);

        final WebTarget wt = target();
        final Response response = wt.path("meters/" + deviceId3.toString()
                + "/" + "888").request().get();

        assertEquals(404, response.getStatus());
    }

    /**
     * Tests creating a meter with POST.
     */
    @Test
    public void testPost() {
        mockMeterService.submit(anyObject());
        expectLastCall().andReturn(meter5).anyTimes();
        replay(mockMeterService);
        replay(mockDeviceService);

        WebTarget wt = target();
        InputStream jsonStream = MetersResourceTest.class
                .getResourceAsStream("post-meter.json");

        Response response = wt.path("meters/of:0000000000000001")
                .request(MediaType.APPLICATION_JSON_TYPE)
                .post(Entity.json(jsonStream));
        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_CREATED));
        String location = response.getLocation().getPath();
        assertThat(location, Matchers.startsWith("/meters/of:0000000000000001/"));
    }

    /**
     * Tests creating a meter with POST, but wrong deviceID.
     */
    @Test
    public void testPostWithWrongDevice() {
        mockMeterService.submit(anyObject());
        expectLastCall().andReturn(meter5).anyTimes();
        replay(mockMeterService);
        replay(mockDeviceService);

        WebTarget wt = target();
        InputStream jsonStream = MetersResourceTest.class
                .getResourceAsStream("post-meter.json");

        Response response = wt.path("meters/of:0000000000000002")
                .request(MediaType.APPLICATION_JSON_TYPE)
                .post(Entity.json(jsonStream));
        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_BAD_REQUEST));
    }

    /**
     * Tests deleting a meter.
     */
    @Test
    public void testDelete() {
        setupMockMeters();
        expect(mockMeterService.getMeter(anyObject(), anyObject()))
                .andReturn(meter5).anyTimes();
        mockMeterService.withdraw(anyObject(), anyObject());
        expectLastCall();
        replay(mockMeterService);

        WebTarget wt = target();

        String location = "/meters/3/555";

        Response deleteResponse = wt.path(location)
                .request(MediaType.APPLICATION_JSON_TYPE)
                .delete();
        assertThat(deleteResponse.getStatus(),
                is(HttpURLConnection.HTTP_NO_CONTENT));
    }
}
