/*
 * Copyright 2016-present 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.pcerest;

import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.hamcrest.Matchers.containsString;
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.Link.Type.DIRECT;

import com.eclipsesource.json.Json;
import com.eclipsesource.json.JsonObject;

import java.io.InputStream;
import java.net.HttpURLConnection;
import java.util.LinkedList;
import java.util.List;
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 javax.ws.rs.NotFoundException;

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.packet.IpAddress;
import org.onlab.rest.BaseResource;
import org.onosproject.codec.CodecService;
import org.onosproject.core.DefaultGroupId;
import org.onosproject.incubator.net.tunnel.DefaultTunnel;
import org.onosproject.incubator.net.tunnel.IpTunnelEndPoint;
import org.onosproject.incubator.net.tunnel.Tunnel;
import org.onosproject.incubator.net.tunnel.TunnelId;
import org.onosproject.incubator.net.tunnel.TunnelEndPoint;
import org.onosproject.incubator.net.tunnel.TunnelName;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.DefaultLink;
import org.onosproject.net.DefaultPath;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.pce.pceservice.api.PceService;
import org.onosproject.pce.pceservice.PcepAnnotationKeys;
import org.onosproject.net.Path;
import org.onosproject.net.PortNumber;
import org.onosproject.net.provider.ProviderId;

/**
 * Unit tests for pce path REST APIs.
 */
public class PcePathResourceTest extends PceResourceTest {
    private final PceService pceService = createMock(PceService.class);
    private final TunnelEndPoint src = IpTunnelEndPoint.ipTunnelPoint(IpAddress.valueOf(23423));
    private final TunnelEndPoint dst = IpTunnelEndPoint.ipTunnelPoint(IpAddress.valueOf(32421));
    private final DefaultGroupId groupId = new DefaultGroupId(92034);
    private final TunnelName tunnelName = TunnelName.tunnelName("TunnelName");
    private final TunnelId tunnelId = TunnelId.valueOf("41654654");
    private final ProviderId producerName = new ProviderId("producer1", "13");
    private Path path;
    private Tunnel tunnel;
    private DeviceId deviceId1;
    private DeviceId deviceId2;
    private DeviceId deviceId3;
    private DeviceId deviceId4;
    private DeviceId deviceId5;
    private PortNumber port1;
    private PortNumber port2;
    private PortNumber port3;
    private PortNumber port4;
    private PortNumber port5;

    /**
     * Sets up the global values for all the tests.
     */
    @Before
    public void setUpTest() {
       // Mock environment setup
       MockPceCodecContext context = new MockPceCodecContext();
       ServiceDirectory testDirectory = new TestServiceDirectory().add(PceService.class, pceService)
                                                                  .add(CodecService.class, context.codecManager());
       BaseResource.setServiceDirectory(testDirectory);

       // Tunnel creation
       // Links
       ProviderId providerId = new ProviderId("of", "foo");
       deviceId1 = DeviceId.deviceId("of:A");
       deviceId2 = DeviceId.deviceId("of:B");
       deviceId3 = DeviceId.deviceId("of:C");
       deviceId4 = DeviceId.deviceId("of:D");
       deviceId5 = DeviceId.deviceId("of:E");
       port1 = PortNumber.portNumber(1);
       port2 = PortNumber.portNumber(2);
       port3 = PortNumber.portNumber(3);
       port4 = PortNumber.portNumber(4);
       port5 = PortNumber.portNumber(5);
       List<Link> linkList = new LinkedList<>();

       Link l1 = DefaultLink.builder()
                            .providerId(providerId)
                            .annotations(DefaultAnnotations.builder().set("key1", "yahoo").build())
                            .src(new ConnectPoint(deviceId1, port1))
                            .dst(new ConnectPoint(deviceId2, port2))
                            .type(DIRECT)
                            .state(Link.State.ACTIVE)
                            .build();
       linkList.add(l1);
       Link l2 = DefaultLink.builder()
                            .providerId(providerId)
                            .annotations(DefaultAnnotations.builder().set("key2", "yahoo").build())
                            .src(new ConnectPoint(deviceId2, port2))
                            .dst(new ConnectPoint(deviceId3, port3))
                            .type(DIRECT)
                            .state(Link.State.ACTIVE)
                            .build();
       linkList.add(l2);
       Link l3 = DefaultLink.builder()
                            .providerId(providerId)
                            .annotations(DefaultAnnotations.builder().set("key3", "yahoo").build())
                            .src(new ConnectPoint(deviceId3, port3))
                            .dst(new ConnectPoint(deviceId4, port4))
                            .type(DIRECT)
                            .state(Link.State.ACTIVE)
                            .build();
       linkList.add(l3);
       Link l4 = DefaultLink.builder()
                            .providerId(providerId)
                            .annotations(DefaultAnnotations.builder().set("key4", "yahoo").build())
                            .src(new ConnectPoint(deviceId4, port4))
                            .dst(new ConnectPoint(deviceId5, port5))
                            .type(DIRECT)
                            .state(Link.State.ACTIVE)
                            .build();
       linkList.add(l4);

       // Path
       path = new DefaultPath(providerId, linkList, 10);

       // Annotations
       DefaultAnnotations.Builder builderAnn = DefaultAnnotations.builder();
       builderAnn.set(PcepAnnotationKeys.LSP_SIG_TYPE, "WITH_SIGNALLING");
       builderAnn.set(PcepAnnotationKeys.COST_TYPE, "COST");
       builderAnn.set(PcepAnnotationKeys.BANDWIDTH, "200");

       // Tunnel
       tunnel = new DefaultTunnel(producerName, src, dst, Tunnel.Type.VXLAN,
                                  Tunnel.State.ACTIVE, groupId, tunnelId,
                                  tunnelName, path, builderAnn.build());
    }

    /**
     * Cleans up.
     */
    @After
    public void tearDownTest() {
    }

    /**
     * Tests the result of the rest api GET when there are no pce paths.
     */
    @Test
    public void testPcePathsEmpty() {
        expect(pceService.queryAllPath())
                         .andReturn(null)
                         .anyTimes();
        replay(pceService);
        WebTarget wt = target();
        String response = wt.path("path").request().get(String.class);
        assertThat(response, is("{\"paths\":[]}"));
    }

    /**
     * Tests the result of a rest api GET for pce path id.
     */
    @Test
    public void testGetTunnelId() {
        expect(pceService.queryPath(anyObject()))
                         .andReturn(tunnel)
                         .anyTimes();
        replay(pceService);

        WebTarget wt = target();
        String response = wt.path("path/1").request().get(String.class);
        JsonObject result = Json.parse(response).asObject();
        assertThat(result, notNullValue());
    }

    /**
     * Tests that a fetch of a non-existent pce path object throws an exception.
     */
    @Test
    public void testBadGet() {
        expect(pceService.queryPath(anyObject()))
                         .andReturn(null)
                         .anyTimes();
        replay(pceService);

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

    /**
     * Tests creating a pce path with POST.
     */
    @Test
    public void testPost() {
        expect(pceService.setupPath(anyObject(), anyObject(), anyObject(), anyObject(), anyObject()))
                         .andReturn(true)
                         .anyTimes();
        replay(pceService);

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

        Response response = wt.path("path")
                              .request(MediaType.APPLICATION_JSON_TYPE)
                              .post(Entity.json(jsonStream));
        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));
    }

    /**
     * Tests creating a pce path with PUT.
     */
    @Test
    public void testPut() {
        expect(pceService.updatePath(anyObject(), anyObject()))
                         .andReturn(true)
                         .anyTimes();
        replay(pceService);

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

        Response response = wt.path("path/1")
                              .request(MediaType.APPLICATION_JSON_TYPE)
                              .put(Entity.json(jsonStream));
        assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));
    }

    /**
     * Tests deleting a pce path.
     */
    @Test
    public void testDelete() {
        expect(pceService.releasePath(anyObject()))
                         .andReturn(true)
                         .anyTimes();
        replay(pceService);

        WebTarget wt = target();

        String location = "path/1";

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