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


import com.google.common.base.Preconditions;
import com.sun.jersey.api.json.JSONWithPadding;
import org.apache.amber.oauth2.common.exception.OAuthSystemException;
import org.apache.amber.oauth2.common.message.OAuthResponse;
import org.apache.commons.lang.NullArgumentException;
import org.apache.commons.lang.StringUtils;

import org.apache.usergrid.management.ApplicationInfo;
import org.apache.usergrid.management.OrganizationInfo;
import org.apache.usergrid.management.export.ExportService;
import org.apache.usergrid.persistence.queue.impl.UsergridAwsCredentials;
import org.apache.usergrid.rest.AbstractContextResource;
import org.apache.usergrid.rest.ApiResponse;
import org.apache.usergrid.rest.applications.ServiceResource;
import org.apache.usergrid.rest.management.organizations.applications.imports.ImportsResource;
import org.apache.usergrid.rest.security.annotations.RequireOrganizationAccess;
import org.apache.usergrid.rest.utils.JSONPUtils;
import org.apache.usergrid.security.oauth.ClientCredentialsInfo;
import org.apache.usergrid.security.providers.SignInAsProvider;
import org.apache.usergrid.security.providers.SignInProviderFactory;
import org.apache.usergrid.services.ServiceManager;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.UUID;

import static javax.servlet.http.HttpServletResponse.SC_ACCEPTED;
import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
import static javax.servlet.http.HttpServletResponse.SC_OK;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import org.apache.usergrid.persistence.EntityManager;
import org.apache.usergrid.persistence.core.util.Health;


@Component("org.apache.usergrid.rest.management.organizations.applications.ApplicationResource")
@Scope("prototype")
@Produces({
    MediaType.APPLICATION_JSON,
    "application/javascript",
    "application/x-javascript",
    "text/ecmascript",
    "application/ecmascript",
    "text/jscript"
})
public class ApplicationResource extends AbstractContextResource {

    private static final Logger logger = LoggerFactory.getLogger(ApplicationResource.class);

    @Autowired
    protected ExportService exportService;

    OrganizationInfo organization;
    UUID applicationId;
    ApplicationInfo application;

    @Autowired
    private SignInProviderFactory signInProviderFactory;


    public ApplicationResource() {
    }


    public ApplicationResource init( OrganizationInfo organization, UUID applicationId ) {
        this.organization = organization;
        this.applicationId = applicationId;
        return this;
    }


    public ApplicationResource init( OrganizationInfo organization, ApplicationInfo application ) {
        this.organization = organization;
        applicationId = application.getId();
        this.application = application;
        return this;
    }



    @RequireOrganizationAccess
    @GET
    public JSONWithPadding getApplication(
            @Context UriInfo ui, @QueryParam("callback") @DefaultValue("callback") String callback )
        throws Exception {

        ApiResponse response = createApiResponse();
        ServiceManager sm = smf.getServiceManager( applicationId );
        response.setAction( "get" );
        response.setApplication( sm.getApplication() );
        response.setParams( ui.getQueryParameters() );
        response.setResults( management.getApplicationMetadata( applicationId ) );
        return new JSONWithPadding( response, callback );
    }


    @RequireOrganizationAccess
    @GET
    @Path("credentials")
    public JSONWithPadding getCredentials(
            @Context UriInfo ui, @QueryParam("callback") @DefaultValue("callback") String callback )
        throws Exception {

        ApiResponse response = createApiResponse();
        response.setAction( "get application client credentials" );

        ClientCredentialsInfo credentials =
                new ClientCredentialsInfo( management.getClientIdForApplication( applicationId ),
                        management.getClientSecretForApplication( applicationId ) );

        response.setCredentials( credentials );
        return new JSONWithPadding( response, callback );
    }


    @RequireOrganizationAccess
    @POST
    @Path("credentials")
    public JSONWithPadding generateCredentials( @Context UriInfo ui,
            @QueryParam("callback") @DefaultValue("callback") String callback )
        throws Exception {

        ApiResponse response = createApiResponse();
        response.setAction( "generate application client credentials" );

        ClientCredentialsInfo credentials =
                new ClientCredentialsInfo( management.getClientIdForApplication( applicationId ),
                        management.newClientSecretForApplication( applicationId ) );

        response.setCredentials( credentials );
        return new JSONWithPadding( response, callback );
    }


    @POST
    @Path("sia-provider")
    @Consumes(APPLICATION_JSON)
    @RequireOrganizationAccess
    public JSONWithPadding configureProvider(
            @Context UriInfo ui,
            @QueryParam("provider_key") String siaProvider,
            Map<String, Object> json,
            @QueryParam("callback")
            @DefaultValue("") String callback )
        throws Exception {

        ApiResponse response = createApiResponse();
        response.setAction( "post signin provider configuration" );

        Preconditions.checkArgument( siaProvider != null, "Sign in provider required" );

        SignInAsProvider signInAsProvider = null;
        if ( StringUtils.equalsIgnoreCase( siaProvider, "facebook" ) ) {
            signInAsProvider = signInProviderFactory.facebook(
                    smf.getServiceManager( applicationId ).getApplication() );
        }
        else if ( StringUtils.equalsIgnoreCase( siaProvider, "pingident" ) ) {
            signInAsProvider = signInProviderFactory.pingident(
                    smf.getServiceManager( applicationId ).getApplication() );
        }
        else if ( StringUtils.equalsIgnoreCase( siaProvider, "foursquare" ) ) {
            signInAsProvider = signInProviderFactory.foursquare(
                    smf.getServiceManager( applicationId ).getApplication() );
        }

        Preconditions.checkArgument( signInAsProvider != null,
                "No signin provider found by that name: " + siaProvider );

        signInAsProvider.saveToConfiguration( json );

        return new JSONWithPadding( response, callback );
    }

    @POST
    @Path("export")
    @Consumes(APPLICATION_JSON)
    @RequireOrganizationAccess
    public Response exportPostJson( @Context UriInfo ui,Map<String, Object> json,
                                    @QueryParam("callback") @DefaultValue("") String callback )
            throws OAuthSystemException {

        UsergridAwsCredentials uac = new UsergridAwsCredentials();

        UUID jobUUID = null;
        Map<String, String> uuidRet = new HashMap<String, String>();

        Map<String,Object> properties;
        Map<String, Object> storage_info;

        try {
            if((properties = ( Map<String, Object> )  json.get( "properties" )) == null){
                throw new NullArgumentException("Could not find 'properties'");
            }
            storage_info = ( Map<String, Object> ) properties.get( "storage_info" );
            String storage_provider = ( String ) properties.get( "storage_provider" );
            if(storage_provider == null) {
                throw new NullArgumentException( "Could not find field 'storage_provider'" );
            }
            if(storage_info == null) {
                throw new NullArgumentException( "Could not find field 'storage_info'" );
            }


            String bucketName = ( String ) storage_info.get( "bucket_location" );
            String accessId = ( String ) storage_info.get( "s3_access_id" );
            String secretKey = ( String ) storage_info.get( "s3_key" );

            if ( bucketName == null ) {
                throw new NullArgumentException( "Could not find field 'bucketName'" );
            }
            if ( accessId == null ) {
                throw new NullArgumentException( "Could not find field 's3_access_id'" );
            }
            if ( secretKey == null ) {

                throw new NullArgumentException( "Could not find field 's3_key'" );
            }

            json.put("organizationId", organization.getUuid());
            json.put( "applicationId",applicationId);

            jobUUID = exportService.schedule( json );
            uuidRet.put( "Export Entity", jobUUID.toString() );
        }
        catch ( NullArgumentException e ) {
            return Response.status( SC_BAD_REQUEST )
                .type( JSONPUtils.jsonMediaType( callback ) )
                .entity( ServiceResource.wrapWithCallback( e.getMessage(), callback ) ).build();
        }
        catch ( Exception e ) {
            // TODO: throw descriptive error message and or include on in the response
            // TODO: fix below, it doesn't work if there is an exception.
            // Make it look like the OauthResponse.
            return Response.status( SC_INTERNAL_SERVER_ERROR )
                .type( JSONPUtils.jsonMediaType( callback ) )
                .entity( ServiceResource.wrapWithCallback( e.getMessage(), callback ) ).build();
        }

        return Response.status( SC_ACCEPTED ).entity( uuidRet ).build();
    }

    @POST
    @Path("collection/{collection_name}/export")
    @Consumes(APPLICATION_JSON)
    @RequireOrganizationAccess
    public Response exportPostJson( @Context UriInfo ui,
            @PathParam( "collection_name" ) String collection_name ,Map<String, Object> json,
            @QueryParam("callback") @DefaultValue("") String callback )
            throws OAuthSystemException {

        UsergridAwsCredentials uac = new UsergridAwsCredentials();
        UUID jobUUID = null;
        String colExport = collection_name;
        Map<String, String> uuidRet = new HashMap<String, String>();

        Map<String,Object> properties;
        Map<String, Object> storage_info;

        try {
            //checkJsonExportProperties(json);
            if((properties = ( Map<String, Object> )  json.get( "properties" )) == null){
                throw new NullArgumentException("Could not find 'properties'");
            }
            storage_info = ( Map<String, Object> ) properties.get( "storage_info" );
            String storage_provider = ( String ) properties.get( "storage_provider" );
            if(storage_provider == null) {
                throw new NullArgumentException( "Could not find field 'storage_provider'" );
            }
            if(storage_info == null) {
                throw new NullArgumentException( "Could not find field 'storage_info'" );
            }

            String bucketName = ( String ) storage_info.get( "bucket_location" );
            String accessId = ( String ) storage_info.get( "s3_access_id" );
            String secretKey = ( String ) storage_info.get( "s3_key" );

            if ( accessId == null ) {
                throw new NullArgumentException( "Could not find field 's3_access_id'" );
            }
            if ( secretKey == null ) {
                throw new NullArgumentException( "Could not find field 's3_key'" );
            }

            if(bucketName == null) {
                throw new NullArgumentException( "Could not find field 'bucketName'" );
            }

            json.put( "organizationId",organization.getUuid() );
            json.put( "applicationId", applicationId);
            json.put( "collectionName", colExport);

            jobUUID = exportService.schedule( json );
            uuidRet.put( "Export Entity", jobUUID.toString() );
        }
        catch ( NullArgumentException e ) {
            return Response.status( SC_BAD_REQUEST )
                .type( JSONPUtils.jsonMediaType( callback ) )
                .entity( ServiceResource.wrapWithCallback( e.getMessage(), callback ) )
                .build();
        }
        catch ( Exception e ) {

            // TODO: throw descriptive error message and or include on in the response
            // TODO: fix below, it doesn't work if there is an exception.
            // Make it look like the OauthResponse.

            OAuthResponse errorMsg = OAuthResponse.errorResponse( SC_INTERNAL_SERVER_ERROR )
                .setErrorDescription( e.getMessage() )
                .buildJSONMessage();

            return Response.status( errorMsg.getResponseStatus() )
                .type( JSONPUtils.jsonMediaType( callback ) )
                .entity( ServiceResource.wrapWithCallback( errorMsg.getBody(), callback ) )
                .build();
        }

        return Response.status( SC_ACCEPTED ).entity( uuidRet ).build();
    }


    @Path( "imports" )
    @RequireOrganizationAccess
    public ImportsResource importGetJson( @Context UriInfo ui,
                                          @QueryParam( "callback" ) @DefaultValue( "" ) String callback )
        throws Exception {


        return getSubResource( ImportsResource.class ).init( organization, application );
    }

    @GET
    @Path("/status")
    public Response getStatus() {

        Map<String, Object> statusMap = new HashMap<String, Object>();

        EntityManager em = emf.getEntityManager( applicationId );
        if ( !emf.getIndexHealth().equals( Health.RED ) ) {
            statusMap.put("message", "Index Health Status RED for application " + applicationId );
            return Response.status( SC_INTERNAL_SERVER_ERROR ).entity( statusMap ).build();
        }

        try {
            if ( em.getApplication() == null ) {
                statusMap.put("message", "Application " + applicationId + " not found");
                return Response.status( SC_NOT_FOUND ).entity( statusMap ).build();
            }

        } catch (Exception ex) {
            statusMap.put("message", "Error looking up application " + applicationId );
            return Response.status( SC_INTERNAL_SERVER_ERROR ).entity( statusMap ).build();
        }

        return Response.status( SC_OK ).entity( null ).build();
    }



    /**
     * Put on application URL will restore application if it was deleted.
     */
    @PUT
    @RequireOrganizationAccess
    public JSONWithPadding executePut(  @Context UriInfo ui, String body,
        @QueryParam("callback") @DefaultValue("callback") String callback ) throws Exception {

        if ( applicationId == null ) {
            throw new IllegalArgumentException("Application ID not specified in request");
        }

        management.restoreApplication( applicationId );

        ApiResponse response = createApiResponse();
        response.setAction( "restore" );
        response.setApplication( emf.getEntityManager( applicationId ).getApplication() );
        response.setParams( ui.getQueryParameters() );

        return new JSONWithPadding( response, callback );
    }


    @DELETE
    @RequireOrganizationAccess
    public JSONWithPadding executeDelete(  @Context UriInfo ui,
        @QueryParam("callback") @DefaultValue("callback") String callback,
        @QueryParam("app_delete_confirm") String confirmDelete) throws Exception {

        if (!"confirm_delete_of_application_and_data".equals( confirmDelete ) ) {
            throw new IllegalArgumentException(
                "Cannot delete application without app_delete_confirm parameter");
        }

        Properties props = management.getProperties();

        // for now, only works in test mode
        String testProp = ( String ) props.get( "usergrid.test" );
        if ( testProp == null || !Boolean.parseBoolean( testProp ) ) {
            throw new UnsupportedOperationException();
        }

        if ( applicationId == null ) {
            throw new IllegalArgumentException("Application ID not specified in request");
        }

        management.deleteApplication( applicationId );

        logger.debug( "ApplicationResource.delete() deleted appId = {}", applicationId);

        ApiResponse response = createApiResponse();
        response.setAction( "delete" );
        response.setApplication(emf.getEntityManager( applicationId ).getApplication());
        response.setParams(ui.getQueryParameters());

        logger.debug( "ApplicationResource.delete() sending response ");

        return new JSONWithPadding( response, callback );
    }

}
