/*
 * 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.resources;

import java.net.HttpURLConnection;
import java.util.HashSet;
import java.util.Set;

import org.junit.Assert;
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.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 org.onosproject.rest.ResourceTest;

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 com.sun.jersey.api.client.UniformInterfaceException;
import com.sun.jersey.api.client.WebResource;

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 {

    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 (subjectClassKey.equals("devices")) {
                return mockDevicesSubjectFactory;
            } else if (subjectClassKey.equals("links")) {
                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 setUp() {
        mockNetworkConfigService = new MockNetworkConfigService();
        ServiceDirectory testDirectory =
                new TestServiceDirectory()
                .add(NetworkConfigService.class, mockNetworkConfigService);
        BaseResource.setServiceDirectory(testDirectory);
    }

    /**
     * Sets up test config data.
     */
    @SuppressWarnings("unchecked")
    public 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 WebResource rs = resource();
        final String response = rs.path("network/configuration").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 WebResource rs = resource();
        final String response = rs.path("network/configuration/devices").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 WebResource rs = resource();

        try {
            final String response = rs.path("network/configuration/nosuchkey").get(String.class);
            fail("GET of non-existent key does not produce an exception " + response);
        } catch (UniformInterfaceException 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 WebResource rs = resource();
        final String response = rs.path("network/configuration").get(String.class);

        final JsonObject result = JsonObject.readFrom(response);
        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 WebResource rs = resource();
        final String response = rs.path("network/configuration/devices").get(String.class);

        final JsonObject result = JsonObject.readFrom(response);
        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 WebResource rs = resource();
        final String response =
                rs.path("network/configuration/devices/device1")
                        .get(String.class);

        final JsonObject result = JsonObject.readFrom(response);
        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 WebResource rs = resource();
        final String response =
                rs.path("network/configuration/devices/device1/basic")
                        .get(String.class);

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

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

        checkBasicAttributes(result);
    }

    // TODO: Add test for DELETE and POST
}
