/*
 * 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 java.io.InputStream;
import java.net.URI;
import java.util.Optional;

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.app.ApplicationAdminService;
import org.onosproject.app.ApplicationService;
import org.onosproject.app.ApplicationState;
import org.onosproject.codec.CodecService;
import org.onosproject.codec.impl.ApplicationCodec;
import org.onosproject.codec.impl.CodecManager;
import org.onosproject.codec.impl.MockCodecContext;
import org.onosproject.core.Application;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.DefaultApplication;
import org.onosproject.core.DefaultApplicationId;
import org.onosproject.core.Version;

import com.eclipsesource.json.JsonArray;
import com.eclipsesource.json.JsonObject;
import com.google.common.collect.ImmutableSet;
import com.sun.jersey.api.client.WebResource;

import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.isA;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
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;

/**
 * Unit tests for applications REST APIs.
 */

public class ApplicationsResourceTest extends ResourceTest {

    private static class MockCodecContextWithService extends MockCodecContext {
        private ApplicationAdminService service;

        MockCodecContextWithService(ApplicationAdminService service) {
            this.service = service;
        }

        @Override
        @SuppressWarnings("unchecked")
        public <T> T get(Class<T> serviceClass) {
            return (T) service;
        }
    }

    private ApplicationAdminService service;
    private ApplicationId id1 = new DefaultApplicationId(1, "app1");
    private ApplicationId id2 = new DefaultApplicationId(2, "app2");
    private ApplicationId id3 = new DefaultApplicationId(3, "app3");
    private ApplicationId id4 = new DefaultApplicationId(4, "app4");

    private static final URI FURL = URI.create("mvn:org.foo-features/1.2a/xml/features");
    private static final Version VER = Version.version(1, 2, "a", null);

    private Application app1 =
            new DefaultApplication(id1, VER,
                    "app1", "origin1", ImmutableSet.of(), Optional.of(FURL),
                    ImmutableSet.of("My Feature"));
    private Application app2 =
            new DefaultApplication(id2, VER,
                    "app2", "origin2", ImmutableSet.of(), Optional.of(FURL),
                    ImmutableSet.of("My Feature"));
    private Application app3 =
            new DefaultApplication(id3, VER,
                    "app3", "origin3", ImmutableSet.of(), Optional.of(FURL),
                    ImmutableSet.of("My Feature"));
    private Application app4 =
            new DefaultApplication(id4, VER,
                    "app4", "origin4", ImmutableSet.of(), Optional.of(FURL),
                    ImmutableSet.of("My Feature"));

    /**
     * Hamcrest matcher to check that an device representation in JSON matches
     * the actual device.
     */
    private static class AppJsonMatcher extends TypeSafeMatcher<JsonObject> {
        private final Application app;
        private String reason = "";

        public AppJsonMatcher(Application appValue) {
            app = appValue;
        }

        @Override
        public boolean matchesSafely(JsonObject jsonApp) {
            // check id
            short jsonId = (short) jsonApp.get("id").asInt();
            if (jsonId != app.id().id()) {
                reason = "id " + app.id().id();
                return false;
            }

            // check name
            String jsonName = jsonApp.get("name").asString();
            if (!jsonName.equals(app.id().name())) {
                reason = "name " + app.id().name();
                return false;
            }

            // check origin
            String jsonOrigin = jsonApp.get("origin").asString();
            if (!jsonOrigin.equals(app.origin())) {
                reason = "manufacturer " + app.origin();
                return false;
            }

            return true;
        }

        @Override
        public void describeTo(Description description) {
            description.appendText(reason);
        }
    }

    /**
     * Factory to allocate an device matcher.
     *
     * @param app application object we are looking for
     * @return matcher
     */
    private static AppJsonMatcher matchesApp(Application app) {
        return new AppJsonMatcher(app);
    }


    @Before
    public void setUp() {
        service = createMock(ApplicationAdminService.class);

        expect(service.getId("one"))
                .andReturn(id1)
                .anyTimes();
        expect(service.getId("two"))
                .andReturn(id2)
                .anyTimes();
        expect(service.getId("three"))
                .andReturn(id3)
                .anyTimes();
        expect(service.getId("four"))
                .andReturn(id4)
                .anyTimes();

        expect(service.getApplication(id3))
                .andReturn(app3)
                .anyTimes();
        expect(service.getState(isA(ApplicationId.class)))
                .andReturn(ApplicationState.ACTIVE)
                .anyTimes();

        // Register the services needed for the test
        CodecManager codecService = new CodecManager();
        codecService.activate();
        ServiceDirectory testDirectory =
                new TestServiceDirectory()
                        .add(ApplicationAdminService.class, service)
                        .add(ApplicationService.class, service)
                        .add(CodecService.class, codecService);

        BaseResource.setServiceDirectory(testDirectory);
    }

    @After
    public void shutDown() {
        verify(service);
    }

    /**
     * Tests a GET of all applications when no applications are present.
     */
    @Test
    public void getAllApplicationsEmpty() {
        expect(service.getApplications())
                .andReturn(ImmutableSet.of());
        replay(service);

        WebResource rs = resource();
        String response = rs.path("applications").get(String.class);
        assertThat(response, is("{\"applications\":[]}"));
    }

    /**
     * Tests a GET of all applications with data.
     */
    @Test
    public void getAllApplicationsPopulated() {
        expect(service.getApplications())
                .andReturn(ImmutableSet.of(app1, app2, app3, app4));
        replay(service);

        WebResource rs = resource();
        String response = rs.path("applications").get(String.class);
        assertThat(response, containsString("{\"applications\":["));

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

        assertThat(result.names(), hasSize(1));
        assertThat(result.names().get(0), is("applications"));

        JsonArray jsonApps = result.get("applications").asArray();
        assertThat(jsonApps, notNullValue());
        assertThat(jsonApps.size(), is(4));

        assertThat(jsonApps.get(0).asObject(), matchesApp(app1));
        assertThat(jsonApps.get(1).asObject(), matchesApp(app2));
        assertThat(jsonApps.get(2).asObject(), matchesApp(app3));
        assertThat(jsonApps.get(3).asObject(), matchesApp(app4));
    }

    /**
     * Tests a GET of a single application.
     */
    @Test
    public void getSingleApplication() {
        replay(service);

        WebResource rs = resource();
        String response = rs.path("applications/three").get(String.class);

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

        assertThat(result, matchesApp(app3));
    }

    /**
     * Tests a DELETE of a single application - this should
     * attempt to uninstall it.
     */
    @Test
    public void deleteApplication() {
        service.uninstall(id3);
        expectLastCall();

        replay(service);

        WebResource rs = resource();
        rs.path("applications/three").delete();
    }

    /**
     * Tests a DELETE of a single active application - this should
     * attempt to uninstall it.
     */
    @Test
    public void deleteActiveApplication() {
        service.deactivate(id3);
        expectLastCall();

        replay(service);

        WebResource rs = resource();
        rs.path("applications/three/active").delete();
    }

    /**
     * Tests a POST operation to the "active" URL.  This should attempt to
     * activate the application.
     */
    @Test
    public void postActiveApplication() {
        service.activate(id3);
        expectLastCall();

        replay(service);

        WebResource rs = resource();
        rs.path("applications/three/active").post();
    }

    /**
     * Tests a POST operation.  This should attempt to
     * install the application.
     */
    @Test
    public void postApplication() {
        expect(service.install(isA(InputStream.class)))
                .andReturn(app4)
                .once();

        replay(service);

        ApplicationCodec codec = new ApplicationCodec();
        String app4Json = codec.encode(app4,
                                       new MockCodecContextWithService(service))
                .asText();

        WebResource rs = resource();
        String response = rs.path("applications").post(String.class, app4Json);

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

        assertThat(result, matchesApp(app4));
    }
}
