/*
 * 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 = 11;
            final int maxExpectedAttributes = 12;

            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();
        expect(mockDeviceService.getLastUpdatedInstant(isA(DeviceId.class)))
                .andReturn(0L)
                .anyTimes();
        expect(mockDeviceService.localStatus(isA(DeviceId.class)))
                .andReturn("")
                .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"));
        }
    }
}
