/*
 * 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.management;


import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;

import org.apache.usergrid.rest.test.resource2point0.model.*;
import org.junit.Ignore;
import org.junit.Test;

import org.apache.usergrid.persistence.index.utils.UUIDUtils;
import org.apache.usergrid.rest.test.resource2point0.AbstractRestIT;
import org.apache.usergrid.rest.test.resource2point0.RestClient;

import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.UniformInterfaceException;
import com.sun.jersey.api.representation.Form;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;


/**
 * Handles all management organization endpoint tests. Any tests that work with organizations specifically can be found here
 */
public class OrganizationsIT extends AbstractRestIT {

    String duplicateUniquePropertyExistsErrorMessage = "duplicate_unique_property_exists";
    String invalidGrantErrorMessage = "invalid_grant";

    /**
     * Tests that a Organization and Owner can be created and that they persist properties and default permissions.
     */
    @Test
    public void createOrgAndOwner() throws Exception {

        //User property to see if owner properties exist when created.
        Map<String, Object> userProperties = new HashMap<String, Object>();
        userProperties.put( "company", "Apigee" );

        //Create organization
        Organization organization = createOrgPayload( "createOrgAndOwner", userProperties );

        //Get back organization response
        Organization organizationResponse = clientSetup.getRestClient().management().orgs().post( organization );

        assertNotNull( organizationResponse );

//        Thread.sleep( 1000 );
//        this.refreshIndex();

        //Creates token
        Token token =
                clientSetup.getRestClient().management().token().post(false,Token.class, new Token( "password",
                        organization.getUsername(), organization.getPassword() ) ,null);
        this.management().token().setToken(token);

        assertNotNull( token );

        //this.refreshIndex();

        //Assert that the get returns the correct org and owner.
        Organization returnedOrg = clientSetup.getRestClient().management().orgs().organization( organization.getOrganization()).get();

        assertTrue( returnedOrg != null && returnedOrg.getName().equals( organization.getOrganization() ) );

        User returnedUser = returnedOrg.getOwner();

        //Assert that the property was retained in the owner of the organization.
        assertNotNull( returnedUser );
        assertEquals( "Apigee", returnedUser.getProperties().get( "company" ) );
    }


    /**
     * Creates a organization with an owner, then attempts to create an organization with the same name ( making sure it
     * fails) When it fails it verifies that the original is still intact.
     * @throws Exception
     */
    @Test
    public void testCreateDuplicateOrgName() throws Exception {

        //Create organization
        Organization organization = createOrgPayload( "testCreateDuplicateOrgName", null );

        Organization orgCreatedResponse = clientSetup.getRestClient().management().orgs().post( organization );
        this.refreshIndex();

        assertNotNull( orgCreatedResponse );

        //Ensure that the token from the newly created organization works.
        Token tokenPayload = new Token( "password", organization.getUsername(), organization.getPassword() );
        Token tokenReturned = clientSetup.getRestClient().management().token().post(false,Token.class, tokenPayload,null );
        this.management().token().setToken(tokenReturned);
        assertNotNull( tokenReturned );

        //Try to create a organization with the same name as an organization that already exists, ensure that it fails
        Organization orgTestDuplicatePayload =
                new Organization( organization.getOrganization(), organization.getUsername() + "test",
                        organization.getEmail() + "test", organization.getName() + "test",
                        organization.getPassword(), null );
        try {
            clientSetup.getRestClient().management().orgs().post( orgTestDuplicatePayload );
            fail("Should not have been able to create duplicate organization");
        }
        catch ( UniformInterfaceException ex ) {
            errorParse( 400,duplicateUniquePropertyExistsErrorMessage, ex );
        }

        // Post to get token of what should be a non existent user due to the failure of creation above

        tokenPayload = new Token( "password", organization.getName() + "test", organization.getPassword() );
        Token tokenError = null;
        try {
            tokenError = clientSetup.getRestClient().management().token().post(false,Token.class, tokenPayload,null );
            fail( "Should not have created user" );
        }
        catch ( UniformInterfaceException ex ) {
            errorParse( 400,invalidGrantErrorMessage, ex );

        }

        assertNull( tokenError );
    }


    /**
     * Tests creation of an organization with a duplicate email. Then checks to make sure correct
     * error message is thrown. Also makes sure that the owner of the duplicate org isn't created
     * while the original is still intact.
     * @throws Exception
     */
    @Test
    public void testCreateDuplicateOrgEmail() throws Exception {

        Organization organization = createOrgPayload( "testCreateDuplicateOrgEmail", null );

        //create the org/owner
        Organization orgCreatedResponse = clientSetup.getRestClient().management().orgs().post( organization );

        this.refreshIndex();

        assertNotNull( orgCreatedResponse );

        //get token from organization that was created to verify it exists.
        Token tokenPayload = new Token( "password", organization.getUsername(), organization.getPassword() );
        Token tokenReturned = clientSetup.getRestClient().management().token().post(Token.class, tokenPayload );

        assertNotNull( tokenReturned );

        //recreate a new payload using a duplicate email
        Organization orgDuplicatePayload = new Organization( organization.getOrganization()+"test",
                organization.getUsername()+"test", organization.getEmail(),
                organization.getName()+"test", organization.getPassword()+"test", null );


        //verify that we cannot create an organization that shares a email with another preexisting organization.
        try {
            clientSetup.getRestClient().management().orgs().post( orgDuplicatePayload );
            fail( "Should not have created organization" );
        }
        catch ( UniformInterfaceException ex ) {
            errorParse( 400,duplicateUniquePropertyExistsErrorMessage,ex);
        }

        //try to get the token from the organization that failed to be created to verify it was not made.
        tokenPayload = new Token( "password", organization.getUsername()+"test", organization.getPassword()+"test" );
        Token tokenError = null;
        try {
            tokenError = clientSetup.getRestClient().management().token().post(false,Token.class, tokenPayload,null );
            fail( "Should not have created organization" );
        }
        catch ( UniformInterfaceException ex ) {
            errorParse( 400,invalidGrantErrorMessage,ex );
        }

        assertNull( tokenError );

    }


    /**
     * Creates a organization by setting the information as part of the queryParameters
     * @throws IOException
     */
    @Test
    public void testOrgPOSTParams() throws IOException {

        //Create organization defaults
        Organization organization =  createOrgPayload( "testOrgPOSTParams",null );

        //Append them to the end as query parameters
        QueryParameters queryParameters = new QueryParameters();
        queryParameters.setKeyValue( "organization",organization.getOrganization());
        queryParameters.setKeyValue( "username",organization.getUsername() );
        queryParameters.setKeyValue( "grant_type","password" );
        queryParameters.setKeyValue( "email",organization.getEmail() );
        queryParameters.setKeyValue( "name",organization.getName() );
        queryParameters.setKeyValue( "password",organization.getPassword() );

        //Post the organization and verify it worked --> old behavior now we get a bad request
        try{
            Organization organizationReturned = clientSetup.getRestClient().management().orgs().post(queryParameters);
            fail();
        }catch (UniformInterfaceException e){
            assertEquals("ensure bad request",e.getResponse().getStatus(), 400);
        }

//        assertNotNull( organizationReturned );
//        assertEquals( organization.getOrganization(), organizationReturned.getName());
//
//        //get token from organization that was created to verify it exists. also sets the current context.
//        Token tokenPayload = new Token( "password", organization.getName(), organization.getPassword() );
//        Token tokenReturned = clientSetup.getRestClient().management().token().post(Token.class, tokenPayload );
//
//        assertNotNull( tokenReturned );
//
//        //Assert that the get returns the correct org and owner.
//        Organization returnedOrg = clientSetup.getRestClient().management().orgs().organization( organization.getOrganization() ).get();
//
//        assertTrue( returnedOrg != null && returnedOrg.getName().equals(organization.getOrganization()) );

    }


    /**
     * Creates a organization by posting a form with the organization data.
     * @throws IOException
     */
    @Test
    public void testOrgPOSTForm() throws IOException {

        Organization organization =  createOrgPayload( "testOrgPOSTForm",null );

        //create the form to hold the organization
        Form form = new Form();
        form.add( "organization", organization.getOrganization() );
        form.add("username", organization.getUsername());
        form.add( "grant_type", "password" );
        form.add( "email", organization.getEmail() );
        form.add( "name", organization.getName() );
        form.add("password", organization.getPassword());

        //Post the organization and verify it worked.
        Organization organizationReturned = clientSetup.getRestClient().management().orgs().post( form );

        assertNotNull( organizationReturned );
        assertEquals(organization.getOrganization(), organizationReturned.getName());

        //get token from organization that was created to verify it exists. also sets the current context.
        Token tokenPayload = new Token( "password", organization.getName(), organization.getPassword() );
        Token tokenReturned = clientSetup.getRestClient().management().token().post(false,Token.class, tokenPayload,null);

        assertNotNull( tokenReturned );

        this.management().token().setToken(tokenReturned);

        //Assert that the get returns the correct org and owner.
        Organization returnedOrg = clientSetup.getRestClient().management().orgs().organization( organization.getOrganization() ).get();

        assertTrue(returnedOrg != null && returnedOrg.getName().equals(organization.getOrganization()));

    }


    /**
     * Returns error from unimplemented delete method by trying to call the delete organization endpoint
     * @throws IOException
     */
    @Ignore("It should return a 501, so when this is fixed the test can be run")
    @Test
    public void noOrgDelete() throws IOException {

        try {
            //Delete default organization
            clientSetup.getRestClient().management().orgs().organization( clientSetup.getOrganizationName() ).delete();
            fail( "Delete is not implemented yet" );
        }catch(UniformInterfaceException uie){
            assertEquals( ClientResponse.Status.NOT_IMPLEMENTED ,uie.getResponse().getStatus());
        }
    }


    /**
     * Creates a regular organization user and then does a get to check the correct username is returned.
     * @throws Exception
     */
    @Test
    public void testCreateOrgUserAndReturnCorrectUsername() throws Exception {
        RestClient restClient = clientSetup.getRestClient();

        //Create adminUser values
        Entity adminUserPayload = new Entity();
        String username = "testCreateOrgUserAndReturnCorrectUsername"+UUIDUtils.newTimeUUID();
        adminUserPayload.put( "username", username );
        adminUserPayload.put( "name", username );
        adminUserPayload.put("email", username + "@usergrid.com");
        adminUserPayload.put("password", username);

        //create adminUser
        ApiResponse adminUserEntityResponse = management().orgs().organization( clientSetup.getOrganizationName() ).users().post(ApiResponse.class, adminUserPayload);

        Entity adminUserResponse = new Entity(adminUserEntityResponse);
        //verify that the response contains the correct data
        assertNotNull( adminUserResponse );
        assertEquals(username, adminUserResponse.get("username"));

        //fetch the stored response
        adminUserResponse = management().users().entity( username ).get(this.getAdminToken(username,username));
        // user = ((LinkedHashMap)((LinkedHashMap)adminUserResponse.get("data")).get("user"));

        //verify that values match stored response
        assertNotNull( adminUserResponse );
        assertEquals( username , adminUserResponse.get( "username" ) );
        assertEquals( username, adminUserResponse.get( "name" ) );
        assertEquals(username + "@usergrid.com", adminUserResponse.get("email"));

    }


    /**
     * Inserts a value into the default organization then update that value and see if the value persists.
     * @throws Exception
     */
    @Test
    public void testOrganizationUpdate() throws Exception {

        RestClient restClient = clientSetup.getRestClient();

        //Setup what will be interested into the organization
        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put( "puppies", 5 );

        Organization orgPayload = clientSetup.getOrganization();
        orgPayload.put( "properties", properties );

        //update the organization.
        management().orgs().organization( clientSetup.getOrganizationName() ).put(orgPayload);

        this.refreshIndex();

        //retrieve the organization
        Organization orgResponse = management().orgs().organization( clientSetup.getOrganizationName() ).get();

        assertEquals(5, orgResponse.getProperties().get("puppies" ));

        //update the value added to the organization
        properties.put( "puppies", 6 );
        orgPayload.put("properties", properties );

        //update the organization.
        management().orgs().organization( clientSetup.getOrganizationName()).put(orgPayload);

        this.refreshIndex();

        orgResponse = management().orgs().organization( clientSetup.getOrganizationName() ).get();

        assertEquals( 6, orgResponse.getProperties().get( "puppies" ));

    }

    /**
     * Create an organization payload with almost the same value for everyfield.
     * @param baseName
     * @param properties
     * @return
     */
    public Organization createOrgPayload(String baseName,Map properties){
        String orgName = baseName + UUIDUtils.newTimeUUID();
        return new Organization( orgName+ UUIDUtils.newTimeUUID(),orgName,orgName+"@usergrid",orgName,orgName, properties);
    }
}
