/*
 * 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;
        }
    }

    public NetworkConfigWebResourceTest() {
        super(CoreWebApplication.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
}
