/*
 * 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.ImmutableList;
import com.google.common.collect.ImmutableMap;
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.onosproject.codec.CodecService;
import org.onosproject.codec.impl.CodecManager;
import org.onosproject.net.DefaultPort;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.MastershipRole;
import org.onosproject.net.Port;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.driver.DefaultDriver;
import org.onosproject.net.driver.DriverService;
import org.onosproject.net.driver.TestBehaviour;
import org.onosproject.net.driver.TestBehaviourImpl;
import org.onosproject.net.driver.TestBehaviourTwo;
import org.onosproject.net.driver.TestBehaviourTwoImpl;

import javax.ws.rs.NotFoundException;
import javax.ws.rs.client.WebTarget;
import java.util.ArrayList;
import java.util.List;

import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.isA;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
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.junit.Assert.fail;
import static org.onosproject.net.NetTestTools.device;
import static org.onosproject.net.NetTestTools.did;
import static org.onosproject.net.PortNumber.portNumber;

/**
 * Unit tests for devices REST APIs.
 */
public class DevicesResourceTest extends ResourceTest {
    DeviceService mockDeviceService;
    DriverService mockDriverService;
    DefaultDriver driver = new DefaultDriver("ovs", new ArrayList<>(), "Circus", "lux", "1.2a",
            ImmutableMap.of(TestBehaviour.class,
                    TestBehaviourImpl.class,
                    TestBehaviourTwo.class,
                    TestBehaviourTwoImpl.class),
            ImmutableMap.of("foo", "bar"));

    /**
     * Hamcrest matcher to check that an device representation in JSON matches
     * the actual device.
     */
    public static class DeviceJsonMatcher extends TypeSafeMatcher<JsonObject> {
        private final Device device;
        private String reason = "";

        public DeviceJsonMatcher(Device deviceValue) {
            device = deviceValue;
        }

        @Override
        public boolean matchesSafely(JsonObject jsonDevice) {
            // check id
            String jsonId = jsonDevice.get("id").asString();
            if (!jsonId.equals(device.id().toString())) {
                reason = "id " + device.id().toString();
                return false;
            }

            // check type
            String jsonType = jsonDevice.get("type").asString();
            if (!jsonType.equals(device.type().toString())) {
                reason = "appId " + device.type().toString();
                return false;
            }

            // check manufacturer
            String jsonManufacturer = jsonDevice.get("mfr").asString();
            if (!jsonManufacturer.equals(device.manufacturer())) {
                reason = "manufacturer " + device.manufacturer();
                return false;
            }

            // check HW version field
            String jsonHwVersion = jsonDevice.get("hw").asString();

            if (!jsonHwVersion.equals(device.hwVersion())) {
                reason = "hw Version " + device.hwVersion();
                return false;
            }

            // check SW version field
            String jsonSwVersion = jsonDevice.get("sw").asString();
            if (!jsonSwVersion.equals(device.swVersion())) {
                reason = "sw Version " + device.swVersion();
                return false;
            }

            // check serial number field
            String jsonSerialNumber = jsonDevice.get("serial").asString();
            if (!jsonSerialNumber.equals(device.serialNumber())) {
                reason = "serial number " + device.serialNumber();
                return false;
            }

            // check chassis id field
            String jsonChassisId = jsonDevice.get("chassisId").asString();
            if (!jsonChassisId.equals(device.chassisId().toString())) {
                reason = "Chassis id " + device.chassisId().toString();
                return false;
            }

            return true;
        }

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

    /**
     * Factory to allocate an device matcher.
     *
     * @param device device object we are looking for
     * @return matcher
     */
    private static DeviceJsonMatcher matchesDevice(Device device) {
        return new DeviceJsonMatcher(device);
    }

    /**
     * Hamcrest matcher to check that an device is represented properly in a JSON
     * array of devices.
     */
    private static class DeviceJsonArrayMatcher extends TypeSafeMatcher<JsonArray> {
        private final Device device;
        private String reason = "";

        public DeviceJsonArrayMatcher(Device deviceValue) {
            device = deviceValue;
        }

        @Override
        public boolean matchesSafely(JsonArray json) {
            final int minExpectedAttributes = 9;
            final int maxExpectedAttributes = 10;

            boolean deviceFound = false;

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

                JsonObject jsonDevice = json.get(jsonDeviceIndex).asObject();

                if (jsonDevice.names().size() < minExpectedAttributes ||
                    jsonDevice.names().size() > maxExpectedAttributes) {
                    reason = "Found a device with the wrong number of attributes";
                    return false;
                }

                String jsonDeviceId = jsonDevice.get("id").asString();
                if (jsonDeviceId.equals(device.id().toString())) {
                    deviceFound = true;

                    //  We found the correct device, check attribute values
                    assertThat(jsonDevice, matchesDevice(device));
                }
            }
            if (!deviceFound) {
                reason = "Device with id " + device.id().toString() + " not found";
                return false;
            } else {
                return true;
            }
        }

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

    /**
     * Factory to allocate an device array matcher.
     *
     * @param device device object we are looking for
     * @return matcher
     */
    private static DeviceJsonArrayMatcher hasDevice(Device device) {
        return new DeviceJsonArrayMatcher(device);
    }

    /**
     * Initializes test mocks and environment.
     */
    @Before
    public void setUpMocks() {
        mockDeviceService = createMock(DeviceService.class);
        mockDriverService = createMock(DriverService.class);
        expect(mockDeviceService.isAvailable(isA(DeviceId.class)))
                .andReturn(true)
                .anyTimes();
        expect(mockDeviceService.getRole(isA(DeviceId.class)))
                .andReturn(MastershipRole.MASTER)
                .anyTimes();


        // Register the services needed for the test
        CodecManager codecService =  new CodecManager();
        codecService.activate();
        ServiceDirectory testDirectory =
                new TestServiceDirectory()
                        .add(DeviceService.class, mockDeviceService)
                        .add(DriverService.class, mockDriverService)
                        .add(CodecService.class, codecService);

        setServiceDirectory(testDirectory);
    }

    /**
     * Verifies test mocks.
     */
    @After
    public void tearDownMocks() {
        verify(mockDeviceService);
    }

    /**
     * Tests the result of the rest api GET when there are no devices.
     */
    @Test
    public void testDevicesEmptyArray() {
        expect(mockDeviceService.getDevices()).andReturn(ImmutableList.of());
        replay(mockDeviceService);

        WebTarget wt = target();
        String response = wt.path("devices").request().get(String.class);
        assertThat(response, is("{\"devices\":[]}"));
    }

    /**
     * Tests the result of the rest api GET when there are devices present.
     */
    @Test
    public void testDevices() {
        Device device1 = device("dev1");
        Device device2 = device("dev2");
        Device device3 = device("dev3");

        expect(mockDeviceService.getDevices())
                .andReturn(ImmutableList.of(device1, device2, device3))
                .anyTimes();

        replay(mockDeviceService);

        expect(mockDriverService.getDriver(did("dev1")))
                .andReturn(driver)
                .anyTimes();

        expect(mockDriverService.getDriver(did("dev2")))
                .andReturn(driver)
                .anyTimes();

        expect(mockDriverService.getDriver(did("dev3")))
                .andReturn(driver)
                .anyTimes();

        replay(mockDriverService);



        WebTarget wt = target();
        String response = wt.path("devices").request().get(String.class);
        assertThat(response, containsString("{\"devices\":["));

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

        assertThat(result.names(), hasSize(1));
        assertThat(result.names().get(0), is("devices"));

        JsonArray jsonDevices = result.get("devices").asArray();
        assertThat(jsonDevices, notNullValue());
        assertThat(jsonDevices.size(), is(3));

        assertThat(jsonDevices, hasDevice(device1));
        assertThat(jsonDevices, hasDevice(device2));
        assertThat(jsonDevices, hasDevice(device3));
    }

    /**
     * Tests the result of a rest api GET for a single device.
     */
    @Test
    public void testDevicesSingle() {

        String deviceIdString = "testdevice";
        DeviceId deviceId = did(deviceIdString);
        Device device = device(deviceIdString);
        expect(mockDeviceService.getDevice(deviceId))
                .andReturn(device)
                .once();
        replay(mockDeviceService);
        expect(mockDriverService.getDriver(deviceId))
                .andReturn(driver)
                .anyTimes();
        replay(mockDriverService);

        WebTarget wt = target();
        String response = wt.path("devices/" + deviceId).request().get(String.class);
        JsonObject result = Json.parse(response).asObject();
        assertThat(result, matchesDevice(device));
    }

    /**
     * Tests the result of a rest api GET for the ports of a single device.
     */
    @Test
    public void testDeviceAndPorts() {

        String deviceIdString = "testdevice";
        DeviceId deviceId = did(deviceIdString);
        Device device = device(deviceIdString);


        Port port1 = new DefaultPort(device, portNumber(1), true);
        Port port2 = new DefaultPort(device, portNumber(2), true);
        Port port3 = new DefaultPort(device, portNumber(3), true);
        List<Port> ports = ImmutableList.of(port1, port2, port3);

        expect(mockDeviceService.getDevice(deviceId))
                .andReturn(device)
                .once();

        expect(mockDeviceService.getPorts(deviceId))
                .andReturn(ports)
                .once();
        replay(mockDeviceService);

        expect(mockDriverService.getDriver(deviceId))
                .andReturn(driver)
                .anyTimes();
        replay(mockDriverService);


        WebTarget wt = target();
        String response =
                wt.path("devices/" + deviceId + "/ports").request()
                    .get(String.class);
        JsonObject result = Json.parse(response).asObject();
        assertThat(result, matchesDevice(device));

        JsonArray jsonPorts = result.get("ports").asArray();
        assertThat(jsonPorts.size(), is(3));
        for (int portIndex = 0; portIndex < jsonPorts.size(); portIndex++) {
            JsonObject jsonPort = jsonPorts.get(portIndex).asObject();

            assertThat(jsonPort.get("port").asString(),
                       is(Integer.toString(portIndex + 1)));
            assertThat(jsonPort.get("isEnabled").asBoolean(),
                       is(true));
            assertThat(jsonPort.get("type").asString(),
                       equalTo("copper"));
            assertThat(jsonPort.get("portSpeed").asLong(),
                    is(1000L));
        }
    }

    /**
     * Tests that a fetch of a non-existent device object throws an exception.
     */
    @Test
    public void testBadGet() {

        expect(mockDeviceService.getDevice(isA(DeviceId.class)))
                .andReturn(null)
                .anyTimes();
        replay(mockDeviceService);

        WebTarget wt = target();
        try {
            wt.path("devices/0").request().get(String.class);
            fail("Fetch of non-existent device did not throw an exception");
        } catch (NotFoundException ex) {
            assertThat(ex.getMessage(),
                    containsString("HTTP 404 Not Found"));
        }
    }
}
