/*
 * 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 com.eclipsesource.json.JsonArray;
import com.eclipsesource.json.JsonObject;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.sun.jersey.api.client.WebResource;
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 java.io.InputStream;
import java.net.URI;
import java.util.Optional;

import static org.easymock.EasyMock.*;
import static org.easymock.EasyMock.isA;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;

/**
 * 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),
                                   ImmutableList.of("My Feature"));
    private Application app2 =
            new DefaultApplication(id2, VER,
                                   "app2", "origin2", ImmutableSet.of(), Optional.of(FURL),
                                   ImmutableList.of("My Feature"));
    private Application app3 =
            new DefaultApplication(id3, VER,
                                   "app3", "origin3", ImmutableSet.of(), Optional.of(FURL),
                                   ImmutableList.of("My Feature"));
    private Application app4 =
            new DefaultApplication(id4, VER,
                                   "app4", "origin4", ImmutableSet.of(), Optional.of(FURL),
                                   ImmutableList.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));
    }
}
