/*
 * Copyright 2015-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.JsonObject;
import com.eclipsesource.json.JsonValue;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.ImmutableSet;
import org.eclipse.jetty.http.HttpStatus;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.osgi.TestServiceDirectory;
import org.onosproject.net.DefaultDevice;
import org.onosproject.net.Device;
import org.onosproject.net.Link;
import org.onosproject.net.config.Config;
import org.onosproject.net.config.NetworkConfigService;
import org.onosproject.net.config.NetworkConfigServiceAdapter;
import org.onosproject.net.config.SubjectFactory;

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

import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.replay;
import static org.hamcrest.MatcherAssert.assertThat;
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.fail;

/**
 * Unit tests for network config web resource.
 */
public class NetworkConfigWebResourceTest extends ResourceTest {

    private MockNetworkConfigService mockNetworkConfigService;

    public class MockDeviceConfig extends Config<Device> {

        final String field1Value;
        final String field2Value;

        MockDeviceConfig(String value1, String value2) {
            field1Value = value1;
            field2Value = value2;
        }

        @Override
        public String key() {
            return "basic";
        }

        @Override
        public JsonNode node() {
            return new ObjectMapper()
                    .createObjectNode()
                    .put("field1", field1Value)
                    .put("field2", field2Value);
        }
    }

    /**
     * Mock config factory for devices.
     */
    private final SubjectFactory<Device> mockDevicesSubjectFactory =
            new SubjectFactory<Device>(Device.class, "devices") {
                @Override
                public Device createSubject(String subjectKey) {
                    DefaultDevice device = createMock(DefaultDevice.class);
                    replay(device);
                    return device;
                }

                @Override
                public Class<Device> subjectClass() {
                    return Device.class;
                }
            };

    /**
     * Mock config factory for links.
     */
    private final SubjectFactory<Link> mockLinksSubjectFactory =
            new SubjectFactory<Link>(Link.class, "links") {
                @Override
                public Link createSubject(String subjectKey) {
                    return null;
                }

                @Override
                public Class<Link> subjectClass() {
                    return Link.class;
                }
            };

    /**
     * Mocked config service.
     */
    class MockNetworkConfigService extends NetworkConfigServiceAdapter {

        Set devicesSubjects = new HashSet<>();
        Set devicesConfigs = new HashSet<>();
        Set linksSubjects = new HashSet();
        Set linksConfigs = new HashSet<>();

        @Override
        public Set<Class> getSubjectClasses() {
            return ImmutableSet.of(Device.class, Link.class);
        }

        @Override
        public SubjectFactory getSubjectFactory(Class subjectClass) {
            if (subjectClass == Device.class) {
                return mockDevicesSubjectFactory;
            } else if (subjectClass == Link.class) {
                return mockLinksSubjectFactory;
            }
            return null;
        }

        @Override
        public SubjectFactory getSubjectFactory(String subjectClassKey) {
            if ("devices".equals(subjectClassKey)) {
                return mockDevicesSubjectFactory;
            } else if ("links".equals(subjectClassKey)) {
                return mockLinksSubjectFactory;
            }
            return null;
        }

        @SuppressWarnings("unchecked")
        @Override
        public <S> Set<S> getSubjects(Class<S> subjectClass) {
            if (subjectClass == Device.class) {
                return devicesSubjects;
            } else if (subjectClass == Link.class) {
                return linksSubjects;
            }
            return null;
        }

        @SuppressWarnings("unchecked")
        @Override
        public <S> Set<? extends Config<S>> getConfigs(S subject) {
            if (subject instanceof Device || subject.toString().contains("device")) {
                return devicesConfigs;
            } else if (subject.toString().contains("link")) {
                return linksConfigs;
            }
            return null;
        }

        @SuppressWarnings("unchecked")
        @Override
        public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) {

            if (configClass == MockDeviceConfig.class) {
                return (C) devicesConfigs.toArray()[0];
            }
            return null;
        }

        @Override
        public Class<? extends Config> getConfigClass(String subjectClassKey, String configKey) {
            return MockDeviceConfig.class;
        }
    }

    /**
     * Sets up mocked config service.
     */
    @Before
    public void setUpMocks() {
        mockNetworkConfigService = new MockNetworkConfigService();
        ServiceDirectory testDirectory =
                new TestServiceDirectory()
                        .add(NetworkConfigService.class, mockNetworkConfigService);
        setServiceDirectory(testDirectory);
    }

    /**
     * Sets up test config data.
     */
    @SuppressWarnings("unchecked")
    private void setUpConfigData() {
        mockNetworkConfigService.devicesSubjects.add("device1");
        mockNetworkConfigService.devicesConfigs.add(new MockDeviceConfig("v1", "v2"));
    }

    /**
     * Tests the result of the rest api GET when there are no configs.
     */
    @Test
    public void testEmptyConfigs() {
        final WebTarget wt = target();
        final String response = wt.path("network/configuration").request().get(String.class);

        assertThat(response, containsString("\"devices\":{}"));
        assertThat(response, containsString("\"links\":{}"));
    }

    /**
     * Tests the result of the rest api GET for a single subject with no configs.
     */
    @Test
    public void testEmptyConfig() {
        final WebTarget wt = target();
        final String response = wt.path("network/configuration/devices").request().get(String.class);

        assertThat(response, is("{}"));
    }

    /**
     * Tests the result of the rest api GET for a single subject that
     * is undefined.
     */
    @Test
    public void testNonExistentConfig() {
        final WebTarget wt = target();

        try {
            final String response = wt.path("network/configuration/nosuchkey").request().get(String.class);
            fail("GET of non-existent key does not produce an exception " + response);
        } catch (NotFoundException e) {
            assertThat(e.getResponse().getStatus(), is(HttpURLConnection.HTTP_NOT_FOUND));
        }
    }

    private void checkBasicAttributes(JsonValue basic) {
        Assert.assertThat(basic.asObject().get("field1").asString(), is("v1"));
        Assert.assertThat(basic.asObject().get("field2").asString(), is("v2"));
    }

    /**
     * Tests the result of the rest api GET when there is a config.
     */
    @Test
    public void testConfigs() {
        setUpConfigData();
        final WebTarget wt = target();
        final String response = wt.path("network/configuration").request().get(String.class);

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

        Assert.assertThat(result.names(), hasSize(2));

        JsonValue devices = result.get("devices");
        Assert.assertThat(devices, notNullValue());

        JsonValue device1 = devices.asObject().get("device1");
        Assert.assertThat(device1, notNullValue());

        JsonValue basic = device1.asObject().get("basic");
        Assert.assertThat(basic, notNullValue());

        checkBasicAttributes(basic);
    }

    /**
     * Tests the result of the rest api single subject key GET when
     * there is a config.
     */
    @Test
    public void testSingleSubjectKeyConfig() {
        setUpConfigData();
        final WebTarget wt = target();
        final String response = wt.path("network/configuration/devices").request().get(String.class);

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

        Assert.assertThat(result.names(), hasSize(1));

        JsonValue device1 = result.asObject().get("device1");
        Assert.assertThat(device1, notNullValue());

        JsonValue basic = device1.asObject().get("basic");
        Assert.assertThat(basic, notNullValue());

        checkBasicAttributes(basic);
    }

    /**
     * Tests the result of the rest api single subject GET when
     * there is a config.
     */
    @Test
    public void testSingleSubjectConfig() {
        setUpConfigData();
        final WebTarget wt = target();
        final String response =
                wt.path("network/configuration/devices/device1")
                        .request()
                        .get(String.class);

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

        Assert.assertThat(result.names(), hasSize(1));

        JsonValue basic = result.asObject().get("basic");
        Assert.assertThat(basic, notNullValue());

        checkBasicAttributes(basic);
    }

    /**
     * Tests the result of the rest api single subject single config GET when
     * there is a config.
     */
    @Test
    public void testSingleSubjectSingleConfig() {
        setUpConfigData();
        final WebTarget wt = target();
        final String response =
                wt.path("network/configuration/devices/device1/basic")
                        .request()
                        .get(String.class);

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

        Assert.assertThat(result.names(), hasSize(2));

        checkBasicAttributes(result);
    }

    /**
     * Tests network configuration with POST and illegal JSON.
     */
    @Test
    public void testBadPost() {
        String json = "this is invalid!";
        WebTarget wt = target();

        Response response = wt.path("network/configuration")
                .request(MediaType.APPLICATION_JSON_TYPE)
                .post(Entity.json(json));
        Assert.assertThat(response.getStatus(), is(HttpURLConnection.HTTP_BAD_REQUEST));
    }

    /**
     * Tests creating a network config with POST.
     */
    @Test
    public void testPost() {
        InputStream jsonStream = IntentsResourceTest.class
                .getResourceAsStream("post-config.json");
        WebTarget wt = target();

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

    /**
     * Tests creating a network config with POST of valid but incorrect JSON.
     */
    @Test
    public void testBadSyntaxPost() {
        InputStream jsonStream = IntentsResourceTest.class
                .getResourceAsStream("post-config-bad-syntax.json");
        WebTarget wt = target();

        Response response = wt.path("network/configuration")
                .request(MediaType.APPLICATION_JSON_TYPE)
                .post(Entity.json(jsonStream));
        Assert.assertThat(response.getStatus(), is(HttpStatus.MULTI_STATUS_207));
    }

    // TODO: Add test for DELETE
}
