/*
 * Copyright 2016-present 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 com.eclipsesource.json.Json;
import com.eclipsesource.json.JsonArray;
import com.eclipsesource.json.JsonObject;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
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.ApplicationRole;
import org.onosproject.core.DefaultApplication;
import org.onosproject.core.DefaultApplicationId;
import org.onosproject.core.Version;

import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import java.io.InputStream;
import java.net.URI;
import java.util.Optional;

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 getService(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, "title1",
                                   "desc1", "origin1", "category1", "url1",
                                   "readme1", new byte[0], ApplicationRole.ADMIN,
                                   ImmutableSet.of(), Optional.of(FURL),
                                   ImmutableList.of("My Feature"), ImmutableList.of());
    private Application app2 =
            new DefaultApplication(id2, VER, "title2",
                                   "desc2", "origin2", "category2", "url2",
                                   "readme2", new byte[0], ApplicationRole.ADMIN,
                                   ImmutableSet.of(), Optional.of(FURL),
                                   ImmutableList.of("My Feature"), ImmutableList.of());
    private Application app3 =
            new DefaultApplication(id3, VER, "title3",
                                   "desc3", "origin3", "category3", "url3",
                                   "readme3", new byte[0], ApplicationRole.ADMIN,
                                   ImmutableSet.of(), Optional.of(FURL),
                                   ImmutableList.of("My Feature"), ImmutableList.of());
    private Application app4 =
            new DefaultApplication(id4, VER, "title4",
                                   "desc4", "origin4", "category4", "url4",
                                   "readme4", new byte[0], ApplicationRole.ADMIN,
                                   ImmutableSet.of(), Optional.of(FURL),
                                   ImmutableList.of("My Feature"), ImmutableList.of());

    /**
     * Hamcrest matcher to check that an application 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 application matcher.
     *
     * @param app application object we are looking for
     * @return matcher
     */
    private static AppJsonMatcher matchesApp(Application app) {
        return new AppJsonMatcher(app);
    }

    /**
     * Initializes test mocks and environment.
     */
    @Before
    public void setUpMocks() {
        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);
    }

    /**
     * Verifies test mocks.
     */
    @After
    public void tearDownMocks() {
        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);

        WebTarget wt = target();
        String response = wt.path("applications").request().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);

        WebTarget wt = target();
        String response = wt.path("applications").request().get(String.class);
        assertThat(response, containsString("{\"applications\":["));

        JsonObject result = Json.parse(response).asObject();
        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);

        WebTarget wt = target();
        String response = wt.path("applications/three").request().get(String.class);

        JsonObject result = Json.parse(response).asObject();
        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);

        WebTarget wt = target();
        wt.path("applications/three").request().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);

        WebTarget wt = target();
        wt.path("applications/three/active").request().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);

        WebTarget wt = target();
        wt.path("applications/three/active").request().post(null);
    }

    /**
     * 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();

        WebTarget wt = target();
        String response = wt.path("applications").request().post(
                Entity.entity(app4Json, MediaType.APPLICATION_OCTET_STREAM), String.class);

        JsonObject result = Json.parse(response).asObject();
        assertThat(result, notNullValue());

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