/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.apache.usergrid.rest.applications;

import com.fasterxml.jackson.databind.JsonNode;
import com.sun.jersey.api.client.ClientResponse.Status;
import com.sun.jersey.api.client.UniformInterfaceException;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.representation.Form;
import org.apache.shiro.codec.Base64;
import org.apache.usergrid.rest.test.resource2point0.AbstractRestIT;
import org.apache.usergrid.rest.test.resource2point0.endpoints.mgmt.OrganizationResource;
import org.apache.usergrid.rest.test.resource2point0.model.ApiResponse;
import org.apache.usergrid.rest.test.resource2point0.model.Application;
import org.apache.usergrid.rest.test.resource2point0.model.Collection;
import org.apache.usergrid.rest.test.resource2point0.model.Credentials;
import org.apache.usergrid.rest.test.resource2point0.model.Entity;
import org.apache.usergrid.rest.test.resource2point0.model.QueryParameters;
import org.apache.usergrid.rest.test.resource2point0.model.Token;
import org.apache.usergrid.rest.test.resource2point0.model.User;
import org.apache.usergrid.utils.MapUtils;
import org.junit.Ignore;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.ws.rs.core.MediaType;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import static org.apache.usergrid.utils.MapUtils.hashMap;
import static org.junit.Assert.*;


/**
 * Invokes methods on ApplicationResource
 */
public class ApplicationResourceIT extends AbstractRestIT {
    private static final Logger logger = LoggerFactory.getLogger(ApplicationResourceIT.class);

    /**
     * Retrieve an application using the organization client credentials
     */
    @Test
    public void applicationWithOrgCredentials() throws Exception {
        //retrieve the credentials
        Credentials orgCredentials = getOrgCredentials();

        //retrieve the app using only the org credentials
        ApiResponse apiResponse = this.org().app(clientSetup.getAppName()).getResource(false)
            .queryParam("grant_type", "client_credentials")
            .queryParam("client_id", orgCredentials.getClientId())
            .queryParam("client_secret", orgCredentials.getClientSecret())
            .accept(MediaType.APPLICATION_JSON)
            .type(MediaType.APPLICATION_JSON_TYPE)
            .get(ApiResponse.class);
        //assert that a valid response is returned without error
        assertNotNull(apiResponse);
        assertNull(apiResponse.getError());
    }

    /**
     * Retrieve an application using the application client credentials
     */
    @Test
    public void applicationWithAppCredentials() throws Exception {

        //retrieve the credentials
        Credentials appCredentials = getAppCredentials();

        //retrieve the app using only the org credentials
        ApiResponse apiResponse = this.app().getResource(false)
            .queryParam("grant_type", "client_credentials")
            .queryParam("client_id", appCredentials.getClientId())
            .queryParam("client_secret", appCredentials.getClientSecret())
            .accept(MediaType.APPLICATION_JSON)
            .type(MediaType.APPLICATION_JSON_TYPE)
            .get(ApiResponse.class);
        //assert that a valid response is returned without error
        assertNotNull(apiResponse);
        assertNull(apiResponse.getError());
    }

    /**
     * Verifies that we return JSON even when no accept header is specified.
     * (for backwards compatibility)
     */
    @Test
    public void jsonForNoAccepts() throws Exception {
        //retrieve the credentials
        Credentials orgCredentials = getOrgCredentials();

        //retrieve the users collection without setting the "Accept" header
        WebResource.Builder builder = this.app().collection("users").getResource(false)
            //Add the org credentials to the query
            .queryParam("grant_type", "client_credentials")
            .queryParam("client_id", orgCredentials.getClientId())
            .queryParam("client_secret", orgCredentials.getClientSecret())
            .type(MediaType.APPLICATION_JSON_TYPE);

        ApiResponse apiResponse = builder.get(ApiResponse.class);
        Collection users = new Collection(apiResponse);
        //assert that a valid response is returned without error
        assertNotNull(users);
        assertNull(users.getResponse().getError());

    }

    /**
     * Verifies that we return JSON even when text/html is requested.
     * (for backwards compatibility)
     */
    @Test
    public void jsonForAcceptsTextHtml() throws Exception {

        //Create the organization resource
        OrganizationResource orgResource = clientSetup.getRestClient()
            .management().orgs().org( clientSetup.getOrganizationName() );

        //retrieve the credentials
        Credentials orgCredentials = new Credentials( orgResource.credentials().get(ApiResponse.class));
        String clientId = orgCredentials.getClientId();
        String clientSecret = orgCredentials.getClientSecret();

        //retrieve the users collection, setting the "Accept" header to text/html
        WebResource.Builder builder = this.app().collection("users").getResource(false)
            //Add the org credentials to the query
            .queryParam("grant_type", "client_credentials")
            .queryParam("client_id", clientId)
            .queryParam("client_secret", clientSecret)
            .accept(MediaType.TEXT_HTML)
            .type(MediaType.APPLICATION_JSON_TYPE);

        ApiResponse apiResponse = builder.get(ApiResponse.class);
        Collection users = new Collection(apiResponse);
        //make sure that a valid response is returned without error
        assertNotNull(users);
        assertNull(users.getResponse().getError());
    }

    /**
     * Retrieve an application using password credentials
     *
     * @throws Exception
     */
    @Test
    public void applicationWithJsonCreds() throws Exception {

        User user = new User(
            "applicationWithJsonCreds",
            "applicationWithJsonCreds",
            "applicationWithJsonCreds@usergrid.org",
            "applicationWithJsonCreds");
        Entity entity = this.app().collection("users").post(user);

        assertNotNull(entity);

        refreshIndex();

        //retrieve the app using a username and password
        QueryParameters params = new QueryParameters()
            .addParam("grant_type", "password")
            .addParam("username", "applicationWithJsonCreds")
            .addParam("password", "applicationWithJsonCreds");
        Token apiResponse = this.app().token().post(params);

        //assert that a valid response is returned without error
        assertNotNull(apiResponse);
        assertNotNull(apiResponse.getAccessToken());
        assertNotNull(apiResponse.getExpirationDate());
    }

    /**
     * Retrieve the root application using client credentials
     *
     * @throws Exception
     */
    @Test
    public void rootApplicationWithOrgCredentials() throws Exception {

        String orgName = clientSetup.getOrganizationName().toLowerCase();
        String appName = clientSetup.getAppName().toLowerCase();
        //retrieve the credentials
        Credentials orgCredentials = getOrgCredentials();

        ApiResponse apiResponse = this.app().getResource(false)
            .queryParam("grant_type", "client_credentials")
            .queryParam("client_id", orgCredentials.getClientId())
            .queryParam("client_secret", orgCredentials.getClientSecret())
            .accept(MediaType.APPLICATION_JSON)
            .type(MediaType.APPLICATION_JSON_TYPE)
            .get(ApiResponse.class);

        // assert that the response returns the correct URI
        assertEquals(apiResponse.getUri(), String.format("http://sometestvalue/%s/%s", orgName, appName));

        //unmarshal the application from the response
        Application application = new Application(apiResponse);

        //assert that the application name is correct
        assertEquals(String.format("%s/%s", orgName, appName), application.get("name"));

        //retrieve the application's roles collection
        apiResponse = this.app().collection("roles").getResource(false)
            .queryParam("grant_type", "client_credentials")
            .queryParam("client_id", orgCredentials.getClientId())
            .queryParam("client_secret", orgCredentials.getClientSecret())
            .accept(MediaType.APPLICATION_JSON)
            .type(MediaType.APPLICATION_JSON_TYPE)
            .get(ApiResponse.class);
        Collection roles = new Collection(apiResponse);
        //assert that we have the correct number of default roles
        assertEquals(3, roles.getNumOfEntities());
    }

    /**
     * Retrieve the client credentials for an application
     */
    @Test
    public void testGetAppCredentials() throws IOException {
        Credentials credentials = getAppCredentials();

        assertNotNull(credentials.getClientId());
        assertNotNull(credentials.getClientSecret());
    }

    /**
     * retrieve the client credentials for an organization
     */
    @Test
    public void testGetOrgCredentials() throws IOException {
        Credentials credentials = getOrgCredentials();

        assertNotNull(credentials.getClientId());
        assertNotNull(credentials.getClientSecret());
    }


    /**
     * Reset an application's client credentials
     */
    @Test
    public void testResetAppCredentials() throws IOException {
        Credentials credentials = this.app().credentials()
            .get(new QueryParameters().addParam("access_token", this.getAdminToken().getAccessToken()), false);

//        assertNull(credentials.entrySet().toString());
        assertNotNull(credentials.getClientId());
        assertNotNull(credentials.getClientSecret());
    }


    @Test
    @Ignore //This is implemented now
    public void noAppDelete() throws IOException {
        String orgName = clientSetup.getOrganizationName().toLowerCase();
        String appName = clientSetup.getAppName().toLowerCase();

        ApiResponse apiResponse = resource().path(String.format("/%s/%s", orgName, appName))
            .queryParam("access_token", this.getAdminToken().getAccessToken())
            .accept(MediaType.APPLICATION_JSON)
            .type(MediaType.APPLICATION_JSON_TYPE)
            .delete(ApiResponse.class);

        assertNotNull(apiResponse.getError());
    }

    /**
     * Test for an exception when a token's TTL is set greater than the maximum
     */
    @Test
    public void ttlOverMax() throws Exception {

        String orgName = clientSetup.getOrganizationName().toLowerCase();
        String appName = clientSetup.getAppName().toLowerCase();
        String username = "username";
        String name = "name";

        //Create a new user entity
        User user = new User(username, name, username + "@usergrid.org", "password");

        //save the user entity
        Entity entity = this.app().collection("users").post(user);
        //assert that it was saved correctly
        assertNotNull(entity);
        refreshIndex();

        //add a ttl to the entity that is greater than the maximum
        entity.chainPut("grant_type", "password").chainPut("ttl", Long.MAX_VALUE);

        try {
            //POST the updated TTL, anticipating an exception
            resource().path(String.format("/%s/%s/token", orgName, appName))
                .accept(MediaType.APPLICATION_JSON)
                .type(MediaType.APPLICATION_JSON_TYPE)
                .post(ApiResponse.class, entity);
            fail("This should cause an exception");
        } catch (UniformInterfaceException uie) {
            assertEquals(
                String.valueOf(Status.BAD_REQUEST.getStatusCode()),
                String.valueOf(uie.getResponse().getStatus()));
        }
    }

    /**
     * Set a token's TTL
     */
    @Test
    public void tokenTtl() throws Exception {

        long ttl = 2000;

        String orgName = clientSetup.getOrganizationName().toLowerCase();
        String appName = clientSetup.getAppName().toLowerCase();
        String username = "username";
        String name = "name";

        //Create a new user entity
        User user = new User(username, name, username + "@usergrid.org", "password");

        //save the entity
        Entity entity = this.app().collection("users").post(user);
        assertNotNull(entity);
        refreshIndex();

        //Retrieve an authentication token for the user, setting the TTL
        Token apiResponse = resource().path(String.format("/%s/%s/token", orgName, appName))
            .queryParam("grant_type", "password")
            .queryParam("username", username)
            .queryParam("password", "password")
            .queryParam("ttl", String.valueOf(ttl))
            .accept(MediaType.APPLICATION_JSON)
            .type(MediaType.APPLICATION_JSON_TYPE)
            .get(Token.class);

        //Set a start time so we can calculate then the token should expire
        long startTime = System.currentTimeMillis();

        //Get the string value of the token
        String token = apiResponse.getAccessToken();
        assertNotNull(token);

        //Get the expiration time of the token (in seconds)
        long expires_in = apiResponse.getExpirationDate();

        //assert that the token's ttl was set correctly
        assertEquals(ttl, expires_in * 1000);

        //retrieve the user entity using the new token
        entity = this.app().collection("users").entity(entity).get(
            new QueryParameters().addParam("access_token", token), false);

        //assert that we got the correct user
        assertEquals(username + "@usergrid.org", entity.get("email"));

        // wait for the token to expire
        Thread.sleep(ttl - (System.currentTimeMillis() - startTime) + 1000);

        try {
            //attempt to retrieve the user again. At this point, the token should have expired
            this.app().collection("users").entity(entity).get(
                new QueryParameters().addParam("access_token", token), false);
            fail("The expired token should cause an exception");
        } catch (UniformInterfaceException uie) {
            assertEquals(Status.UNAUTHORIZED.getStatusCode(), uie.getResponse().getStatus());
        }

    }

    /**
     * Attempt to set the TTL to an invalid value
     *
     * @throws Exception
     */
    @Test
    public void ttlNan() throws Exception {

        String orgName = clientSetup.getOrganizationName().toLowerCase();
        String appName = clientSetup.getAppName().toLowerCase();
        String username = "username";
        String name = "name";

        //Create a new user entity
        User user = new User(username, name, username + "@usergrid.org", "password");

        //save the entity
        Entity entity = this.app().collection("users").post(user);
        assertNotNull(entity);
        refreshIndex();

        try {
            //Retrieve a token for the new user, setting the TTL to an invalid value
            resource().path(String.format("/%s/%s/token", orgName, appName))
                .queryParam("grant_type", "password")
                .queryParam("username", username)
                .queryParam("password", "password")
                .queryParam("ttl", "derp")
                .accept(MediaType.APPLICATION_JSON)
                .type(MediaType.APPLICATION_JSON_TYPE)
                .get(ApiResponse.class);
            fail("The invalid TTL should cause an exception");

        } catch (UniformInterfaceException uie) {
            //TODO should this be handled and returned as a Status.BAD_REQUEST?
            //Status.INTERNAL_SERVER_ERROR is thrown because Jersey throws a NumberFormatException
            assertEquals(Status.INTERNAL_SERVER_ERROR, uie.getResponse().getClientResponseStatus());
        }

    }

    /**
     * Update the default auth token TTL for an application
     */
    @Test
    public void updateAccessTokenTtl() throws Exception {

        String orgName = clientSetup.getOrganizationName().toLowerCase();
        String appName = clientSetup.getAppName().toLowerCase();
        String username = "username";
        String name = "name";

        //Create a new user entity
        User user = new User(username, name, username + "@usergrid.org", "password");

        //save the entity
        Entity entity = this.app().collection("users").post(user);
        assertNotNull(entity);
        refreshIndex();
        //Retrieve an authentication token for the user
        Token tokenResponse = this.app().getResource(false).path("token")
            .queryParam("grant_type", "password")
            .queryParam("username", username)
            .queryParam("password", "password")
            .accept( MediaType.APPLICATION_JSON )
            .type( MediaType.APPLICATION_JSON_TYPE )
            .get( Token.class );

        String token = tokenResponse.getAccessToken();
        assertNotNull(token);

        //Retrieve the expiration time of the token. Should be set to the default of 1 day
        long expires_in = tokenResponse.getExpirationDate();
        assertEquals(604800, expires_in);

        //Set the default TTL of the application to a date far in the future
        this.app().getResource(false)
            .queryParam("access_token", token)
            .accept(MediaType.APPLICATION_JSON)
            .type(MediaType.APPLICATION_JSON_TYPE)
            .put(Token.class, new MapUtils.HashMapBuilder<String, String>().map("accesstokenttl", "31536000000"));

        //Create a new token for the user
        tokenResponse = this.app().token().getResource(false)
            .queryParam("grant_type", "password")
            .queryParam("username", username)
            .queryParam("password", "password")
            .accept(MediaType.APPLICATION_JSON)
            .type(MediaType.APPLICATION_JSON_TYPE)
            .get(Token.class);

        //assert that the new token has the new default TTL
        assertEquals(31536000, tokenResponse.getExpirationDate().intValue());

    }

    /**
     * Retrieve an oauth authorization using invalid credentials
     */
    @Test
    @Ignore("viewable return types are not working in embedded tomcat 7.x")
    public void authorizationCodeWithWrongCredentials() throws Exception {
        //Create form input with bogus credentials
        Form payload = new Form();
        payload.add("username", "wrong_user");
        payload.add("password", "wrong_password");
        payload.add("response_type", "code");
        payload.add("scope", "none");
        payload.add("redirect_uri", "http://www.my_test.com");

        //POST the form to the authorization endpoint
        String apiResponse = clientSetup.getRestClient().management().authorize().getResource().type( MediaType.APPLICATION_FORM_URLENCODED_TYPE ).accept(MediaType.TEXT_HTML).post(String.class, payload);

        //Assert that an appropriate error message is returned
        assertTrue(apiResponse.contains("Username or password do not match"));
    }


    /**
     * retrieve an oauth authorization using invalid application client credentials
     */
    @Test
    //we have authorize response only with username/password - client_id/secret not considered
    public void authorizeWithInvalidClientIdRaisesError() throws Exception {
        //GET the application authorization endpoint using bogus client credentials
        String apiResponse = clientSetup.getRestClient().management().authorize().getResource(true)
            .queryParam("response_type", "code")
            .queryParam("client_id", "invalid_client_id")
            .queryParam("redirect_uri", "http://www.my_test.com")
            .accept(MediaType.TEXT_HTML)
            .get(String.class);
        //Assert that an appropriate error message is returned
        //assertTrue(apiResponse.contains("Unable to authenticate (OAuth). Invalid client_id."));
    }

    /**
     * Retrieve an oauth authorization using valid client credentials
     */
    @Test
    //we have authorize response only with username/password - client_id/secret not considered
    public void authorizationCodeWithValidCredentials() throws Exception {
        //retrieve the credentials
        Credentials orgCredentials = getOrgCredentials();

        //Create form input with valid credentials
        Form payload = new Form();
        payload.add("response_type", "code");
        payload.add("grant_type", "client_credentials");
        payload.add("client_id", orgCredentials.getClientId());
        payload.add("client_secret", orgCredentials.getClientSecret());
        payload.add("scope", "none");
        payload.add("redirect_uri", "http://www.my_test.com");

        //Set the client to not follow the initial redirect returned by the stack
        client().setFollowRedirects(false);

        try {
            //POST the form to the authorization endpoint
            clientSetup.getRestClient().management().authorize().getResource().accept(MediaType.TEXT_HTML).post(String.class, payload);
        } catch (UniformInterfaceException uie) {
            assertEquals(String.valueOf(Status.TEMPORARY_REDIRECT.getStatusCode()), uie.getResponse().getStatus());
        }

    }

    /**
     * Retrieve an access token using HTTP Basic authentication
     */
    @Test
    public void clientCredentialsFlowWithBasicAuthentication() throws Exception {
        //retrieve the credentials
        Credentials orgCredentials = getOrgCredentials();
        String clientId = orgCredentials.getClientId();
        String clientSecret = orgCredentials.getClientSecret();

        //encode the credentials
        String clientCredentials = clientId + ":" + clientSecret;
        String token = Base64.encodeToString(clientCredentials.getBytes());

        Map<String, String> map = new HashMap<>(1);
        map.put("grant_type", "client_credentials");
        //GET the token endpoint, adding the basic auth header
        Token apiResponse = clientSetup.getRestClient().management().token().getResource(false)
            //add the auth header
            .header("Authorization", "Basic " + token)
            .accept(MediaType.APPLICATION_JSON)
            .type(MediaType.APPLICATION_JSON_TYPE)
            .post(Token.class, map);

        //Assert that a valid token with a valid TTL is returned
        assertNotNull("A valid response was returned.", apiResponse);
        assertNull("There is no error.", apiResponse.getError());
        assertNotNull("It has access_token.", apiResponse.getAccessToken());
        assertNotNull("It has expires_in.", apiResponse.getExpirationDate());
    }

    /**
     * Retrieve an access token using HTTP Basic authentication
     */
    @Test
    @Ignore
    //Are we trying to generate token with token? Couldn't find enpoint that accepts token for generating token
    public void clientCredentialsFlowWithHeaderAuthorization() throws Exception {
        //retrieve the credentials
        Credentials orgCredentials = getAppCredentials();
        String clientId = orgCredentials.getClientId();
        String clientSecret = orgCredentials.getClientSecret();

        Token token = clientSetup.getRestClient().management().token()
            .post(Token.class,new Token("client_credentials", clientId, clientSecret));

        //GET the token endpoint, adding authorization header
        Token apiResponse = this.app().token().getResource(false)
            //add the auth header
            .header("Authorization", "Bearer " + token.getAccessToken())
            .accept(MediaType.APPLICATION_JSON)
            .type(MediaType.APPLICATION_JSON_TYPE)
            .post(Token.class, hashMap("grant_type", "client_credentials"));

        //Assert that a valid token with a valid TTL is returned
        assertNotNull("A valid response was returned.", apiResponse);
        assertNull("There is no error.", apiResponse.getError());
        assertNotNull("It has access_token.", apiResponse.getAccessToken());
        assertNotNull("It has expires_in.", apiResponse.getExpirationDate());
    }

    /**
     * Retrieve an authentication token using form input
     */
    @Test
    public void clientCredentialsFlowWithPayload() throws Exception {
        //retrieve the credentials
        Credentials orgCredentials = getOrgCredentials();
        String clientId = orgCredentials.getClientId();
        String clientSecret = orgCredentials.getClientSecret();

        //Create form input
        Form payload = new Form();
        payload.add("grant_type", "client_credentials");
        payload.add("client_id", clientId);
        payload.add("client_secret", clientSecret);

        //POST the form to the application token endpoint
        Token apiResponse = this.app().token().getResource(false)
            .accept(MediaType.APPLICATION_JSON)
            .type(MediaType.APPLICATION_FORM_URLENCODED_TYPE)
            .post(Token.class, payload);

        //Assert that a valid token with a valid TTL is returned
        assertNotNull("It has access_token.", apiResponse.getAccessToken());
        assertNotNull("It has expires_in.", apiResponse.getExpirationDate());
    }


    /**
     * Retrieve an authentication token using a combination of form input and payload
     */
    @Test
    public void clientCredentialsFlowWithHeaderAuthorizationAndPayload() throws Exception {
        //retrieve the credentials
        Credentials orgCredentials = getOrgCredentials();
        String clientId = orgCredentials.getClientId();
        String clientSecret = orgCredentials.getClientSecret();

        //Encode the credentials
        String clientCredentials = clientId + ":" + clientSecret;
        String token = Base64.encodeToString(clientCredentials.getBytes());

        //POST the form to the application token endpoint along with the payload
        Token apiResponse = this.app().token().getResource(false)
            .header("Authorization", "Basic " + token)
            .accept(MediaType.APPLICATION_JSON)
            .type(MediaType.APPLICATION_JSON_TYPE)
            .post(Token.class, hashMap("grant_type", "client_credentials"));

        //Assert that a valid token with a valid TTL is returned
        assertNotNull("It has access_token.", apiResponse.getAccessToken());
        assertNotNull("It has expires_in.", apiResponse.getExpirationDate());
    }

    /**
     * Ensure that the Apigee Mobile Analytics config returns valid JSON
     */
    @Test
    public void validateApigeeApmConfigAPP() throws IOException {
        String orgName = clientSetup.getOrganizationName().toLowerCase();
        String appName = clientSetup.getAppName().toLowerCase();

        try {
            //GET the APM endpoint
            String response = resource().path(String.format("/%s/%s/apm/apigeeMobileConfig", orgName, appName))
                .accept(MediaType.APPLICATION_JSON)
                .type(MediaType.APPLICATION_JSON_TYPE)
                .get(String.class);
            //Parse the response
            JsonNode node = mapper.readTree(response);

            //if things are kosher then JSON should have value for instaOpsApplicationId
            assertTrue("it's valid json for APM", node.has("instaOpsApplicationId"));
        } catch (UniformInterfaceException uie) {
            //Validate that APM config exists
            assertNotEquals("APM Config API exists", Status.NOT_FOUND,
                uie.getResponse().getStatus()); //i.e It should not be "Not Found"
        }
    }


    /**
     * Retrieve an application token using organization credentials
     */
    @Test
    public void appTokenFromOrgCreds() throws Exception {
        //retrieve the organization credentials
        Credentials orgCredentials = getOrgCredentials();
        String clientId = orgCredentials.getClientId();
        String clientSecret = orgCredentials.getClientSecret();

        //use the org credentials to create an application token
        Token token = this.app().token().post(new Token("client_credentials", clientId, clientSecret));

        //Assert that we received an authorization token
        assertNotNull(token);

        int ttl = token.getExpirationDate().intValue();
        //check it's 1 day, should be the same as the default
        assertEquals(604800, ttl);

        //retrieve the users collection for the application using the new token
        ApiResponse response = this.app().collection("users").getResource(true, token).get(ApiResponse.class);
        //assert that we did not receive an error
        assertNull(response.getError());
    }


    /**
     * Retrieve an application token using application credentials
     */
    @Test
    public void appTokenFromAppCreds() throws Exception {
        //retrieve the app credentials
        Credentials appCredentials = getAppCredentials();
        String clientId = appCredentials.getClientId();
        String clientSecret = appCredentials.getClientSecret();

        Token token = this.app().token().post(new Token("client_credentials", clientId, clientSecret));
        //Assert that we received an authorization token
        assertNotNull(token);
        assertNotNull(token.getAccessToken());
        assertNotNull(token.getExpirationDate());

        int ttl = token.getExpirationDate().intValue();
        //check it's 1 day, should be the same as the default
        assertEquals(604800, ttl);

        //retrieve the users collection for the application using the new token
        ApiResponse response = this.app().collection("users").getResource(true, token).get(ApiResponse.class);
        //assert that we did not receive an error
        assertNull(response.getError());
    }

    /**
     * Get the client credentials for the current app
     * @return Credentials
     */
    public Credentials getAppCredentials() throws IOException {
        return new Credentials (this.app().credentials().get(ApiResponse.class,null,true));
    }

    /**
     * Get the client credentials for the current organization
     * @return Credentials
     */
    public Credentials getOrgCredentials() throws IOException {
        String orgName = clientSetup.getOrganizationName().toLowerCase();
        return new Credentials( clientSetup.getRestClient().management().orgs().org( orgName ).credentials().get(ApiResponse.class,null,true) );

    }
}
