/*
 * 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 com.sun.jersey.test.framework.JerseyTest;

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 JerseyTest {
    LinkService mockLinkService;

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

    /**
     * Constructs the test.
     */
    public LinksResourceTest() {
        super("org.onosproject.rest");
    }

    /**
     * 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 (jsonLink.names().size() != expectedAttributes) {
                    reason = "Found a link with the wrong number of attributes";
                    return false;
                }

                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);
    }


    @Before
    public void setUp() {
        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);
    }

    @After
    public void tearDown() throws Exception {
        super.tearDown();
        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));
    }
}
