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


    @Override
    @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));
    }
}
