/*
 * 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.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import javax.annotation.Nonnull;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.Weigher;
import org.apache.commons.io.FileUtils;
import org.apache.felix.webconsole.SimpleWebConsolePlugin;
import org.apache.sling.commons.json.JSONException;
import org.apache.sling.commons.json.io.JSONWriter;
import org.osgi.framework.BundleContext;

class TracerLogServlet extends SimpleWebConsolePlugin implements TraceLogRecorder {
    static final String ATTR_RECORDING = TracerLogServlet.class.getName();

    public static final String CLEAR = "clear";

    private static final String LABEL = "tracer";

    public static final String HEADER_TRACER_RECORDING = "Sling-Tracer-Record";

    public static final String HEADER_TRACER_REQUEST_ID = "Sling-Tracer-Request-Id";

    public static final String HEADER_TRACER_PROTOCOL_VERSION = "Sling-Tracer-Protocol-Version";

    public static final int TRACER_PROTOCOL_VERSION = 1;

    private final Cache<String, JSONRecording> cache;

    private final boolean compressRecording;

    private final int cacheSizeInMB;

    private final long cacheDurationInSecs;

    private final boolean gzipResponse;

    public TracerLogServlet(BundleContext context){
        this(context,
                LogTracer.PROP_TRACER_SERVLET_CACHE_SIZE_DEFAULT,
                LogTracer.PROP_TRACER_SERVLET_CACHE_DURATION_DEFAULT,
                LogTracer.PROP_TRACER_SERVLET_COMPRESS_DEFAULT,
                LogTracer.PROP_TRACER_SERVLET_GZIP_RESPONSE_DEFAULT
        );
    }

    public TracerLogServlet(BundleContext context, int cacheSizeInMB, long cacheDurationInSecs,
                            boolean compressionEnabled, boolean gzipResponse) {
        super(LABEL, "Sling Tracer", "Sling", null);
        this.compressRecording = compressionEnabled;
        this.cacheDurationInSecs = cacheDurationInSecs;
        this.cacheSizeInMB = cacheSizeInMB;
        this.gzipResponse = compressionEnabled && gzipResponse;
        this.cache = CacheBuilder.newBuilder()
                .maximumWeight(cacheSizeInMB * FileUtils.ONE_MB)
                .weigher(new Weigher<String, JSONRecording>() {
                    @Override
                    public int weigh(@Nonnull  String key, @Nonnull JSONRecording value) {
                        return value.size();
                    }
                })
                .expireAfterAccess(cacheDurationInSecs, TimeUnit.SECONDS)
                .recordStats()
                .build();
        register(context);
    }

    boolean isCompressRecording() {
        return compressRecording;
    }

    public boolean isGzipResponse() {
        return gzipResponse;
    }

    int getCacheSizeInMB() {
        return cacheSizeInMB;
    }

    long getCacheDurationInSecs() {
        return cacheDurationInSecs;
    }

    //~-----------------------------------------------< WebConsole Plugin >

    @Override
    protected void renderContent(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        if (isHtmlRequest(request)){
            PrintWriter pw = response.getWriter();
            renderStatus(pw);
            renderRequests(pw);
        } else {
            String requestId = getRequestId(request);
            prepareJSONResponse(response);
            try {
                boolean responseDone = false;
                if (requestId != null) {
                    JSONRecording recording = cache.getIfPresent(requestId);
                    if (recording != null){
                        boolean shouldGZip = prepareForGZipResponse(request, response);
                        responseDone = recording.render(response.getOutputStream(), shouldGZip);
                    }
                }

                if (!responseDone) {
                    PrintWriter pw = response.getWriter();
                    JSONWriter jw = new JSONWriter(pw);
                    jw.object();
                    jw.key("error").value("Not found");
                    jw.endObject();
                }
            } catch (JSONException e) {
                throw new ServletException(e);
            }
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws IOException {
        if (req.getParameter(CLEAR) != null) {
            resetCache();
            resp.sendRedirect(req.getRequestURI());
        }
    }

    @Override
    protected boolean isHtmlRequest(HttpServletRequest request) {
        return request.getRequestURI().endsWith(LABEL);
    }

    private boolean prepareForGZipResponse(HttpServletRequest request, HttpServletResponse response) {
        if (!gzipResponse) {
            return false;
        }

        String acceptEncoding = request.getHeader("Accept-Encoding");
        boolean acceptsGzip = acceptEncoding != null && accepts(acceptEncoding, "gzip");

        if (acceptsGzip) {
            response.setHeader("Content-Encoding", "gzip");
        }
        return acceptsGzip;
    }

    /**
     * Returns true if the given accept header accepts the given value.
     * @param acceptHeader The accept header.
     * @param toAccept The value to be accepted.
     * @return True if the given accept header accepts the given value.
     */
    private static boolean accepts(String acceptHeader, String toAccept) {
        return acceptHeader.contains(toAccept) || acceptHeader.contains("*/*");
    }

    private static void prepareJSONResponse(HttpServletResponse response) {
        response.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");
    }

    private void renderStatus(PrintWriter pw) {
        pw.printf("<p class='statline'>Log Tracer Recordings: %d recordings, %s memory " +
                "(Max %dMB, Expired in %d secs)</p>%n", cache.size(),
                memorySize(), cacheSizeInMB, cacheDurationInSecs);

        pw.println("<div class='ui-widget-header ui-corner-top buttonGroup'>");
        pw.println("<span style='float: left; margin-left: 1em'>Tracer Recordings</span>");
        pw.println("<form method='POST'><input type='hidden' name='clear' value='clear'><input type='submit' value='Clear' class='ui-state-default ui-corner-all'></form>");
        pw.println("</div>");
    }

    private String memorySize() {
        long size = 0;
        for (JSONRecording r : cache.asMap().values()){
            size += r.size();
        }
        return humanReadableByteCount(size);
    }

    private void renderRequests(PrintWriter pw) {
        if (cache.size() > 0){
            pw.println("<ol>");
            List<JSONRecording> recordings = new ArrayList<JSONRecording>(cache.asMap().values());
            SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss");
            Collections.sort(recordings);
            for (JSONRecording r : recordings){
                String id = r.getRequestId();
                String date = sdf.format(new Date(r.getStart()));
                pw.printf("<li>%s - <a href='%s/%s.json'>%s</a> - %s (%s) (%dms)</li>",
                        date, LABEL, id, id,
                        r.getUri(),
                        humanReadableByteCount(r.size()),
                        r.getTimeTaken());
            }
            pw.println("</ol>");
        }
    }

    private static String getRequestId(HttpServletRequest request) {
        String requestUri = request.getRequestURI();
        int lastSlash = requestUri.lastIndexOf('/');
        int lastDot = requestUri.indexOf('.', lastSlash + 1);
        if (lastDot > 0){
            return requestUri.substring(lastSlash + 1, lastDot);
        }
        return null;
    }

    //~-----------------------------------------------< TraceLogRecorder >

    @Override
    public Recording startRecording(HttpServletRequest request, HttpServletResponse response) {
        if (request.getHeader(HEADER_TRACER_RECORDING) == null){
            return Recording.NOOP;
        }

        if (request.getAttribute(ATTR_RECORDING) != null){
            //Already processed
            return getRecordingForRequest(request);
        }

        String requestId = generateRequestId();
        JSONRecording recording = record(requestId, request);

        response.setHeader(HEADER_TRACER_REQUEST_ID, requestId);
        response.setHeader(HEADER_TRACER_PROTOCOL_VERSION, String.valueOf(TRACER_PROTOCOL_VERSION));

        return recording;
    }

    @Override
    public Recording getRecordingForRequest(HttpServletRequest request) {
        Recording recording = (Recording) request.getAttribute(ATTR_RECORDING);
        if (recording == null){
            recording = Recording.NOOP;
        }
        return recording;
    }

    @Override
    public void endRecording(HttpServletRequest httpRequest, Recording recording) {
        if (recording instanceof JSONRecording) {
            JSONRecording r = (JSONRecording) recording;
            r.done();
            cache.put(r.getRequestId(), r);
        }
        httpRequest.removeAttribute(ATTR_RECORDING);
    }

    Recording getRecording(String requestId) {
        Recording recording = cache.getIfPresent(requestId);
        return recording == null ? Recording.NOOP : recording;
    }

    private JSONRecording record(String requestId, HttpServletRequest request) {
        JSONRecording data = new JSONRecording(requestId, request, compressRecording);
        request.setAttribute(ATTR_RECORDING, data);
        return data;
    }

    private static String generateRequestId() {
        return UUID.randomUUID().toString();
    }

    /**
     * Returns a human-readable version of the file size, where the input represents
     * a specific number of bytes. Based on http://stackoverflow.com/a/3758880/1035417
     */
    @SuppressWarnings("Duplicates")
    private static String humanReadableByteCount(long bytes) {
        if (bytes < 0) {
            return "0";
        }
        int unit = 1000;
        if (bytes < unit) {
            return bytes + " B";
        }
        int exp = (int) (Math.log(bytes) / Math.log(unit));
        char pre = "kMGTPE".charAt(exp - 1);
        return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre);
    }

    void resetCache(){
        cache.invalidateAll();
    }
}
