package com.atlassian.stash.internal.rest.log;

import com.atlassian.bitbucket.rest.BadRequestException;
import com.atlassian.bitbucket.rest.RestErrors;
import com.atlassian.bitbucket.rest.util.ResponseFactory;
import com.atlassian.bitbucket.rest.util.RestUtils;
import com.atlassian.plugins.rest.common.security.AnonymousAllowed;
import com.atlassian.bitbucket.log.LoggingService;
import com.atlassian.bitbucket.rest.log.RestLogLevel;
import com.sun.jersey.spi.resource.Singleton;

import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

@Consumes(MediaType.APPLICATION_JSON)
@Path("logs")
@Produces(RestUtils.APPLICATION_JSON_UTF8)
@Singleton
@AnonymousAllowed
public class LoggingResource {

    private final LoggingService loggingService;

    public LoggingResource(LoggingService loggingService) {
        this.loggingService = loggingService;
    }

    /**
     * Retrieve the current log level for a given logger.
     * <p>
     * The authenticated user must have <strong>ADMIN</strong> permission or higher to call this resource.
     *
     * @param loggerName the name of the logger.
     *
     * @response.representation.200.mediaType application/json
     * @response.representation.200.qname logLevel
     * @response.representation.200.example {@link RestLogLevel#EXAMPLE}
     * @response.representation.200.doc The log level of the logger.
     *
     * @response.representation.401.mediaType application/json
     * @response.representation.401.qname errors
     * @response.representation.401.example {@link RestErrors#EXAMPLE}
     * @response.representation.401.doc The currently authenticated user has insufficient permissions
     *                                  to retrieve the log level.
     */
    @Path("logger/{loggerName}")
    @GET
    public Response getLevel(@PathParam("loggerName") String loggerName) {
        String level = loggingService.getLevel(loggerName);

        return ResponseFactory.ok(new RestLogLevel(level)).build();
    }

    /**
     * Retrieve the current log level for the root logger.
     * <p>
     * The authenticated user must have <strong>ADMIN</strong> permission or higher to call this resource.
     *
     * @response.representation.200.mediaType application/json
     * @response.representation.200.qname logLevel
     * @response.representation.200.example {@link RestLogLevel#EXAMPLE}
     * @response.representation.200.doc The log level of the logger.
     *
     * @response.representation.401.mediaType application/json
     * @response.representation.401.qname errors
     * @response.representation.401.example {@link RestErrors#EXAMPLE}
     * @response.representation.401.doc The currently authenticated user has insufficient permissions
     *                                  to retrieve the log level.
     */
    @Path("rootLogger")
    @GET
    public Response getRootLevel() {
        String level = loggingService.getRootLevel();

        return ResponseFactory.ok(new RestLogLevel(level)).build();
    }

    /**
     * Set the current log level for a given logger.
     * <p>
     * The authenticated user must have <strong>ADMIN</strong> permission or higher to call this resource.
     *
     * @param loggerName the name of the logger.
     * @param levelName the level to set the logger to. Either TRACE, DEBUG, INFO, WARN or ERROR
     *
     * @response.representation.204.mediaType application/json
     * @response.representation.204.doc The log level was successfully changed.
     *
     * @response.representation.400.mediaType application/json
     * @response.representation.400.qname errors
     * @response.representation.400.example {@link RestErrors#EXAMPLE}
     * @response.representation.400.doc The log level was invalid.
     *
     * @response.representation.401.mediaType application/json
     * @response.representation.401.qname errors
     * @response.representation.401.example {@link RestErrors#EXAMPLE}
     * @response.representation.401.doc The currently authenticated user has insufficient permissions
     *                                  to set the log level.
     */
    @Path("logger/{loggerName}/{levelName}")
    @PUT
    public Response setLevel(@PathParam("loggerName") String loggerName,
                             @PathParam("levelName") String levelName) {
        try {
            loggingService.setLevel(loggerName, levelName);

            return ResponseFactory.noContent().build();
        } catch (IllegalArgumentException e) {
            throw  translate(e);
        }
    }

    /**
     * Set the current log level for the root logger.
     * <p>
     * The authenticated user must have <strong>ADMIN</strong> permission or higher to call this resource.
     *
     * @param levelName the level to set the logger to. Either TRACE, DEBUG, INFO, WARN or ERROR
     *
     * @response.representation.204.mediaType application/json
     * @response.representation.204.doc The log level was successfully changed.
     *
     * @response.representation.400.mediaType application/json
     * @response.representation.400.qname errors
     * @response.representation.400.example {@link RestErrors#EXAMPLE}
     * @response.representation.400.doc The log level was invalid.
     *
     * @response.representation.401.mediaType application/json
     * @response.representation.401.qname errors
     * @response.representation.401.example {@link RestErrors#EXAMPLE}
     * @response.representation.401.doc The currently authenticated user has insufficient permissions
     *                                  to retrieve the log level.
     */
    @Path("rootLogger/{levelName}")
    @PUT
    public Response setRootLevel(@PathParam("levelName") String levelName) {
        try {
            loggingService.setRootLevel(levelName);
            
            return ResponseFactory.noContent().build();
        } catch (IllegalArgumentException e) {
            throw  translate(e);
        }
    }
    
    private BadRequestException translate(IllegalArgumentException e) {
        return new BadRequestException(e.getMessage());
    }
}
