/*
 * Copyright 2015 Open Networking Laboratory
 *
 * 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;

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.rest.BaseResource;
import org.onosproject.codec.CodecService;
import org.onosproject.codec.impl.CodecManager;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.link.LinkService;

import com.eclipsesource.json.JsonArray;
import com.eclipsesource.json.JsonObject;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.sun.jersey.api.client.WebResource;

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.hasSize;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
import static org.onosproject.net.NetTestTools.link;

/**
 * Unit tests for links REST APIs.
 */
public class LinksResourceTest extends ResourceTest {
    LinkService mockLinkService;

    Link link1 = link("src1", 1, "dst1", 1);
    Link link2 = link("src2", 2, "dst2", 2);
    Link link3 = link("src3", 3, "dst3", 3);

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

        public LinkJsonMatcher(Link linkValue) {
            link = linkValue;
        }

        @Override
        public boolean matchesSafely(JsonObject jsonLink) {
            JsonObject jsonSrc = jsonLink.get("src").asObject();
            String jsonSrcDevice = jsonSrc.get("device").asString();
            String jsonSrcPort = jsonSrc.get("port").asString();

            JsonObject jsonDst = jsonLink.get("dst").asObject();
            String jsonDstDevice = jsonDst.get("device").asString();
            String jsonDstPort = jsonDst.get("port").asString();

            return jsonSrcDevice.equals(link.src().deviceId().toString()) &&
                   jsonSrcPort.equals(link.src().port().toString()) &&
                   jsonDstDevice.equals(link.dst().deviceId().toString()) &&
                   jsonDstPort.equals(link.dst().port().toString());
        }

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

    /**
     * Factory to allocate an link matcher.
     *
     * @param link link object we are looking for
     * @return matcher
     */
    private static LinkJsonMatcher matchesLink(Link link) {
        return new LinkJsonMatcher(link);
    }

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

        public LinkJsonArrayMatcher(Link linkValue) {
            link = linkValue;
        }

        @Override
        public boolean matchesSafely(JsonArray json) {
            final int expectedAttributes = 2;

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

                JsonObject jsonLink = json.get(jsonLinkIndex).asObject();

                if (matchesLink(link).matchesSafely(jsonLink)) {
                    return true;
                }
            }
            return false;
        }

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

    /**
     * Factory to allocate an link array matcher.
     *
     * @param link link object we are looking for
     * @return matcher
     */
    private static LinkJsonArrayMatcher hasLink(Link link) {
        return new LinkJsonArrayMatcher(link);
    }

    /**
     * Initializes test mocks and environment.
     */
    @Before
    public void setUpTest() {
        mockLinkService = createMock(LinkService.class);

        // Register the services needed for the test
        CodecManager codecService =  new CodecManager();
        codecService.activate();
        ServiceDirectory testDirectory =
                new TestServiceDirectory()
                        .add(LinkService.class, mockLinkService)
                        .add(CodecService.class, codecService);

        BaseResource.setServiceDirectory(testDirectory);
    }

    /**
     * Tears down and verifies test mocks and environment.
     */
    @After
    public void tearDownTest() {
        verify(mockLinkService);
    }

    /**
     * Tests the result of the rest api GET when there are no links.
     */
    @Test
    public void testLinksEmptyArray() {
        expect(mockLinkService.getLinks()).andReturn(ImmutableList.of());
        replay(mockLinkService);

        WebResource rs = resource();
        String response = rs.path("links").get(String.class);
        assertThat(response, is("{\"links\":[]}"));
    }

    /**
     * Tests the result of the rest api GET when there are links present.
     */
    @Test
    public void testLinks() {
        expect(mockLinkService.getLinks())
                .andReturn(ImmutableList.of(link1, link2, link3))
                .anyTimes();

        replay(mockLinkService);

        WebResource rs = resource();
        String response = rs.path("links").get(String.class);
        assertThat(response, containsString("{\"links\":["));

        JsonObject result = JsonObject.readFrom(response);
        assertThat(result, notNullValue());

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

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

        assertThat(jsonLinks, hasLink(link1));
        assertThat(jsonLinks, hasLink(link2));
        assertThat(jsonLinks, hasLink(link3));
    }

    /**
     * Tests the result of the rest api GET of links for a specific device.
     */
    @Test
    public void testLinksByDevice() {
        expect(mockLinkService.getDeviceLinks(isA(DeviceId.class)))
                .andReturn(ImmutableSet.of(link2))
                .anyTimes();

        replay(mockLinkService);

        WebResource rs = resource();
        String response = rs
                .path("links")
                .queryParam("device", "src2")
                .get(String.class);
        assertThat(response, containsString("{\"links\":["));

        JsonObject result = JsonObject.readFrom(response);
        assertThat(result, notNullValue());

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

        JsonArray jsonLinks = result.get("links").asArray();
        assertThat(jsonLinks, notNullValue());
        assertThat(jsonLinks.size(), is(1));

        assertThat(jsonLinks, hasLink(link2));
    }

    /**
     * Tests the result of the rest api GET of links for a specific device
     * and port.
     */
    @Test
    public void testLinksByDevicePort() {

        expect(mockLinkService.getLinks(isA(ConnectPoint.class)))
                .andReturn(ImmutableSet.of(link2))
                .anyTimes();

        replay(mockLinkService);

        WebResource rs = resource();
        String response = rs
                .path("links")
                .queryParam("device", "src2")
                .queryParam("port", "2")
                .get(String.class);
        assertThat(response, containsString("{\"links\":["));

        JsonObject result = JsonObject.readFrom(response);
        assertThat(result, notNullValue());

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

        JsonArray jsonLinks = result.get("links").asArray();
        assertThat(jsonLinks, notNullValue());
        assertThat(jsonLinks.size(), is(1));

        assertThat(jsonLinks, hasLink(link2));
    }

    /**
     * Tests the result of the rest api GET of links for a specific
     * device, port, and direction.
     */
    @Test
    public void testLinksByDevicePortDirection() {

        expect(mockLinkService.getIngressLinks(isA(ConnectPoint.class)))
                .andReturn(ImmutableSet.of(link2))
                .anyTimes();

        replay(mockLinkService);

        WebResource rs = resource();
        String response = rs
                .path("links")
                .queryParam("device", "src2")
                .queryParam("port", "2")
                .queryParam("direction", "INGRESS")
                .get(String.class);
        assertThat(response, containsString("{\"links\":["));

        JsonObject result = JsonObject.readFrom(response);
        assertThat(result, notNullValue());

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

        JsonArray jsonLinks = result.get("links").asArray();
        assertThat(jsonLinks, notNullValue());
        assertThat(jsonLinks.size(), is(1));

        assertThat(jsonLinks, hasLink(link2));
    }

    /**
     * Tests the result of the rest api GET of links for a specific
     * device and direction.
     */
    @Test
    public void testLinksByDeviceDirection() {

        expect(mockLinkService.getDeviceIngressLinks(isA(DeviceId.class)))
                .andReturn(ImmutableSet.of(link2))
                .anyTimes();

        replay(mockLinkService);

        WebResource rs = resource();
        String response = rs
                .path("links")
                .queryParam("device", "src2")
                .queryParam("direction", "INGRESS")
                .get(String.class);
        assertThat(response, containsString("{\"links\":["));

        JsonObject result = JsonObject.readFrom(response);
        assertThat(result, notNullValue());

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

        JsonArray jsonLinks = result.get("links").asArray();
        assertThat(jsonLinks, notNullValue());
        assertThat(jsonLinks.size(), is(1));

        assertThat(jsonLinks, hasLink(link2));
    }
}
