/*
 * 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.sling.tracer.internal;

import java.util.Arrays;

import ch.qos.logback.classic.Level;
import ch.qos.logback.core.helpers.CyclicBuffer;
import org.apache.sling.api.request.RequestProgressTracker;
import org.slf4j.helpers.FormattingTuple;
import org.slf4j.helpers.MessageFormatter;

class TracerContext {
    static final String QUERY_LOGGER = "org.apache.jackrabbit.oak.query.QueryEngineImpl";

    /**
     * Following queries are internal to Oak and are fired for login/access control
     * etc. They should be ignored. With Oak 1.2+ such queries are logged at trace
     * level (OAK-2304)
     */
    private static final String[] IGNORABLE_QUERIES = {
            "SELECT * FROM [nt:base] WHERE [jcr:uuid] = $id",
            "SELECT * FROM [nt:base] WHERE PROPERTY([rep:members], 'WeakReference') = $uuid",
            "SELECT * FROM [rep:Authorizable]WHERE [rep:principalName] = $principalName",
    };

    private static final int LOG_BUFFER_SIZE = 50;
    /*
     * In memory buffer to store logs till RequestProgressTracker is registered.
     * This would be required for those case where TracerContext is created at
     * normal Filter level which gets invoked before Sling layer is hit.
     *
     * Later when Sling layer is hit and SlingTracerFilter is invoked
     * then it would register the RequestProgressTracker and then these inmemory logs
     * would be dumped there
     */
    private CyclicBuffer<String> buffer;
    private RequestProgressTracker progressTracker;
    private int queryCount;
    private final TracerConfig[] tracers;
    private final Recording recording;

    public TracerContext(TracerConfig[] tracers, Recording recording) {
        this.tracers = tracers;
        this.recording = recording;

        //Say if the list is like com.foo;level=trace,com.foo.bar;level=info.
        // Then first config would result in a match and later config would
        // not be able to suppress the logs from a child category
        //To handle such cases we sort the config. With having more depth i.e. more specific
        //coming first and others later
        Arrays.sort(tracers);
    }

    /**
     * Finds and returns the matching TracerConfig for given logger and level
     * If non null it indicates that logging should proceed
     */
    public TracerConfig findMatchingConfig(String logger, Level level) {
        for (TracerConfig tc : tracers) {
            TracerConfig.MatchResult mr = tc.match(logger, level);
            if (mr == TracerConfig.MatchResult.MATCH_LOG) {
                return tc;
            } else if (mr == TracerConfig.MatchResult.MATCH_NO_LOG) {
                return null;
            }
        }
        return null;
    }

    public boolean log(TracerConfig tc, Level level, String logger, String format, Object[] params) {
        FormattingTuple tuple = null;
        if (QUERY_LOGGER.equals(logger)
                && params != null && params.length == 2) {
            if (logQuery(String.valueOf(params[1]))){
                //Get original log message
                tuple = logWithLoggerName(logger, format, params);
            }
        } else {
            tuple = logWithLoggerName(logger, format, params);
        }

        if (tuple != null) {
            recording.log(tc, level, logger, tuple);
        }
        return tuple != null;
    }

    public void recordCategory(String loggerName) {
        recording.recordCategory(loggerName);
    }

    public void done() {
        if (queryCount > 0) {
            progressTracker.log("JCR Query Count {0}", queryCount);
        }
    }

    /**
     * Registers the progress tracker and also logs all the in memory logs
     * collected so far to the tracker
     */
    public void registerProgressTracker(RequestProgressTracker requestProgressTracker) {
        this.progressTracker = requestProgressTracker;
        if (buffer != null) {
            for (String msg : buffer.asList()) {
                progressTracker.log(msg);
            }
            buffer = null;
        }
    }

    private FormattingTuple logWithLoggerName(String loggerName, String format, Object... params) {
        FormattingTuple tuple = MessageFormatter.arrayFormat(format, params);
        String msg = tuple.getMessage();
        msg = "[" + loggerName + "] " + msg;
        if (progressTracker == null) {
            if (buffer == null) {
                buffer = new CyclicBuffer<String>(LOG_BUFFER_SIZE);
            }
            buffer.add(msg);
        } else {
            progressTracker.log(msg);
        }
        return tuple;
    }

    private boolean logQuery(String query) {
        if (ignorableQuery(query)) {
            return false;
        }
        queryCount++;
        return true;
    }

    private boolean ignorableQuery(String msg) {
        for (String ignorableQuery : IGNORABLE_QUERIES) {
            if (msg.contains(ignorableQuery)) {
                return true;
            }
        }
        return false;
    }
}
