package com.atlassian.bitbucket.mesh.logback;

import ch.qos.logback.classic.spi.ILoggingEvent;
import com.atlassian.bitbucket.mesh.request.RequestContext;
import com.atlassian.bitbucket.mesh.request.RequestManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nonnull;

import static java.util.Objects.requireNonNull;

/**
 * Handles emitting access logs from the {@link RequestManager}. Rather than relying on the MDC, or any thread-local
 * state (which can easily end up cleared by the time "o" lines are written), we ensure that the {@link RequestContext}
 * and the "i" or "o" value are provided as arguments on the {@link ILoggingEvent} so the log can be appropriately
 * formatted.
 * <p>
 * See the following for how the logs are formatted:
 * <ul>
 *     <li>{@link AccessLogEncoder} for file and text console logs</li>
 *     <li>{@link AccessLogJsonProvider} for JSON logs</li>
 * </ul>
 */
public class AccessLog {

    static final String PHASE_END = "o";
    static final String PHASE_START = "i";

    private static final Logger accessLog = LoggerFactory.getLogger("mesh.access-log");

    public AccessLog() {
        throw new UnsupportedOperationException(getClass().getSimpleName() + " is not intended to be instantiated");
    }

    /**
     * Writes an entry to the access log denoting the end of the specified {@link RequestContext}.
     *
     * @param context the ended request
     */
    public static void end(@Nonnull RequestContext context) {
        accessLog.info("Message is unused. {} {}", requireNonNull(context, "context"), PHASE_END);
    }

    /**
     * Writes an entry to the access log denoting the start of the specified {@link RequestContext}.
     *
     * @param context the started request
     */
    public static void start(@Nonnull RequestContext context) {
        accessLog.info("Message is unused. {} {}", requireNonNull(context, "context"), PHASE_START);
    }
}
