/*
 * 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.felix.status.impl;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Writer;
import java.text.MessageFormat;
import java.util.Date;
import java.util.zip.Deflater;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.felix.status.PrinterMode;
import org.apache.felix.status.StatusPrinterHandler;
import org.apache.felix.status.StatusPrinterManager;

/**
 * The web console plugin for a status printer.
 */
public abstract class AbstractWebConsolePlugin extends HttpServlet {

    private static final long serialVersionUID = 1L;

    /** The status printer manager. */
    protected final StatusPrinterManager statusPrinterManager;

    /**
     * Constructor
     * @param statusPrinterManager The manager
     */
    AbstractWebConsolePlugin(final StatusPrinterManager statusPrinterManager) {
        this.statusPrinterManager = statusPrinterManager;
    }

    protected abstract StatusPrinterHandler getStatusPrinterHandler();

    private void printConfigurationStatus( final ConfigurationWriter pw,
            final PrinterMode mode,
            final StatusPrinterHandler handler )
    throws IOException {
        if ( handler == null ) {
            for(final StatusPrinterHandler sph : this.statusPrinterManager.getHandlers(mode)) {
                pw.printStatus(mode, sph);
            }
        } else {
            if ( handler.supports(mode) ) {
                pw.printStatus(mode, handler);
            }
        }
    }

    /**
     * Sets response headers to force the client to not cache the response
     * sent back. This method must be called before the response is committed
     * otherwise it will have no effect.
     * <p>
     * This method sets the <code>Cache-Control</code>, <code>Expires</code>,
     * and <code>Pragma</code> headers.
     *
     * @param response The response for which to set the cache prevention
     */
    private final void setNoCache(final HttpServletResponse response) {
        response.setHeader("Cache-Control", "no-cache"); //$NON-NLS-1$ //$NON-NLS-2$
        response.addHeader("Cache-Control", "no-store"); //$NON-NLS-1$ //$NON-NLS-2$
        response.addHeader("Cache-Control", "must-revalidate"); //$NON-NLS-1$ //$NON-NLS-2$
        response.addHeader("Cache-Control", "max-age=0"); //$NON-NLS-1$ //$NON-NLS-2$
        response.setHeader("Expires", "Thu, 01 Jan 1970 01:00:00 GMT"); //$NON-NLS-1$ //$NON-NLS-2$
        response.setHeader("Pragma", "no-cache"); //$NON-NLS-1$ //$NON-NLS-2$
    }

    @Override
    protected void doGet(final HttpServletRequest request,
            final HttpServletResponse response)
    throws ServletException, IOException {
        this.setNoCache( response );

        // full request?
        final StatusPrinterHandler handler;
        if ( request.getPathInfo().lastIndexOf('/') > 0 ) {
            handler = null; // all;
        } else {
            handler = this.getStatusPrinterHandler();
            if ( handler == null ) {
                response.sendError( HttpServletResponse.SC_NOT_FOUND );
                return;
            }
        }

        if ( request.getPathInfo().endsWith( ".txt" ) ) { //$NON-NLS-2$
            response.setContentType( "text/plain; charset=utf-8" ); //$NON-NLS-2$
            final ConfigurationWriter pw = new PlainTextConfigurationWriter( response.getWriter() );
            printConfigurationStatus( pw, PrinterMode.TEXT, handler );
            pw.flush();
        } else if ( request.getPathInfo().endsWith( ".zip" ) ) { //$NON-NLS-2$
            String type = getServletContext().getMimeType( request.getPathInfo() );
            if ( type == null ) {
                type = "application/x-zip"; //$NON-NLS-2$
            }
            response.setContentType( type );

            final ZipOutputStream zip = new ZipOutputStream( response.getOutputStream() );
            zip.setLevel( Deflater.BEST_SPEED );
            zip.setMethod( ZipOutputStream.DEFLATED );

            final Date now = new Date();
            // create time stamp entry
            final ZipEntry entry = new ZipEntry( "timestamp.txt" ); //$NON-NLS-2$
            entry.setTime(now.getTime());
            zip.putNextEntry( entry );
            final StringBuilder sb = new StringBuilder();
            sb.append("Date: ");
            synchronized ( StatusPrinterAdapter.DISPLAY_DATE_FORMAT )                             {
                sb.append(StatusPrinterAdapter.DISPLAY_DATE_FORMAT.format(now));
            }
            sb.append(" (");
            sb.append(String.valueOf(now.getTime()));
            sb.append(")\n");

            zip.write(sb.toString().getBytes("UTF-8"));
            zip.closeEntry();

            final ZipConfigurationWriter pw = new ZipConfigurationWriter( zip );
            printConfigurationStatus( pw, PrinterMode.ZIP_FILE_TEXT, handler );
            pw.counter = 0;
            printConfigurationStatus( pw, PrinterMode.ZIP_FILE_JSON, handler );

            zip.finish();
        } else if ( request.getPathInfo().endsWith( ".nfo" ) ) {
            if ( handler == null ) {
                response.sendError( HttpServletResponse.SC_NOT_FOUND);
                return;
            }
            response.setContentType( "text/html; charset=utf-8" );

            final HtmlConfigurationWriter pw = new HtmlConfigurationWriter( response.getWriter() );
            pw.println ( "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"" );
            pw.println ( "  \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">" );
            pw.println ( "<html xmlns=\"http://www.w3.org/1999/xhtml\">" );
            pw.println ( "<head><title>dummy</title></head><body><div>" );

            if ( handler.supports(PrinterMode.HTML_BODY) ) {
                handler.print(PrinterMode.HTML_BODY, pw);
            } else {
                pw.enableFilter( true );
                handler.print(PrinterMode.TEXT, pw);
                pw.enableFilter( false );
            }
            pw.println( "</div></body></html>" );
            return;
        } else if ( request.getPathInfo().endsWith(".json") ) {
            if ( handler == null ) {
                response.sendError( HttpServletResponse.SC_NOT_FOUND);
                return;
            }
            response.setContentType( "application/json" ); //$NON-NLS-1$
            response.setCharacterEncoding( "UTF-8" ); //$NON-NLS-1$

            final JSONConfigurationWriter jcw = new JSONConfigurationWriter(response.getWriter());
            printConfigurationStatus( jcw, PrinterMode.JSON, handler );
        } else {
            if ( handler == null ) {
                response.sendError( HttpServletResponse.SC_NOT_FOUND);
                return;
            }
            final HtmlConfigurationWriter pw = new HtmlConfigurationWriter(response.getWriter());
            pw.println("<script type=\"text/javascript\">");
            pw.println("// <![CDATA[");
            pw.println("function pad(value) { if ( value < 10 ) { return '0' + value;} return '' + value;}");
            pw.println("function downloadDump(ext, full) {");
            pw.println("  if (full) {");
            pw.println("    var now = new Date();");
            pw.println("    var name = \"configuration-status-\" + now.getUTCFullYear() + pad(now.getUTCMonth() + 1) + pad(now.getUTCDate()) + \"-\" + pad(now.getUTCHours()) + pad(now.getUTCMinutes()) + pad(now.getUTCSeconds()) + \".\";");
            pw.println("    location.href = location.href + \"/\" + name + ext;");
            pw.println("  } else {");
            pw.println("    location.href = location.href + '.' + ext;");
            pw.println("  }");
            pw.println("}");

            pw.println("$(document).ready(function() {");
            pw.println("    $('.downloadTxt').click(function() { downloadDump('txt', false)});");
            pw.println("    $('.downloadJson').click(function() { downloadDump('json', false)});");
            pw.println("    $('.downloadZip').click(function() { downloadDump('zip', false)});");
            pw.println("    $('.downloadFullZip').click(function() { downloadDump('zip', true)});");
            pw.println("    $('.downloadFullTxt').click(function() { downloadDump('txt', true)});");
            pw.println("});");
            pw.println("// ]]>");
            pw.println("</script>");
            pw.println( "<br/><p class=\"statline\">");

            final Date currentTime = new Date();
            synchronized ( StatusPrinterAdapter.DISPLAY_DATE_FORMAT )                             {
                pw.print("Date: ");
                pw.println(StatusPrinterAdapter.DISPLAY_DATE_FORMAT.format(currentTime));
            }

            pw.print("<button type=\"button\" class=\"downloadFullZip\" style=\"float: right; margin-right: 30px; margin-top: 5px;\">Download Full Zip</button>");
            pw.print("<button type=\"button\" class=\"downloadFullTxt\" style=\"float: right; margin-right: 30px; margin-top: 5px;\">Download Full Text</button>");

            if ( handler.supports(PrinterMode.JSON) ) {
                pw.print("<button type=\"button\" class=\"downloadJson\" style=\"float: right; margin-right: 30px; margin-top: 5px;\">Download As JSON</button>");
            }
            if ( handler.supports(PrinterMode.ZIP_FILE_TEXT) || handler.supports(PrinterMode.ZIP_FILE_JSON) ) {
                pw.print("<button type=\"button\" class=\"downloadZip\" style=\"float: right; margin-right: 30px; margin-top: 5px;\">Download As Zip</button>");
            }
            if ( handler.supports(PrinterMode.TEXT ) ) {
                pw.print("<button type=\"button\" class=\"downloadTxt\" style=\"float: right; margin-right: 30px; margin-top: 5px;\">Download As Text</button>");
            }

            pw.println("<br/>&nbsp;</p>"); // status line
            pw.print("<div>");
            if ( handler.supports(PrinterMode.HTML_BODY) ) {
                handler.print(PrinterMode.HTML_BODY, pw);
            } else {
                pw.enableFilter( true );
                handler.print(PrinterMode.TEXT, pw);
                pw.enableFilter( false );
            }
            pw.print("</div>");
        }
    }

    /**
     * Base class for all configuration writers.
     */
    private abstract static class ConfigurationWriter extends PrintWriter {

        ConfigurationWriter( final Writer delegatee ) {
            super( delegatee );
        }

        protected void title( final String title ) throws IOException {
            // dummy implementation
        }


        protected void end() throws IOException {
            // dummy implementation
        }

        public void printStatus(
                final PrinterMode mode,
                final StatusPrinterHandler handler)
        throws IOException {
            this.title(handler.getTitle());
            handler.print(mode, this);
            this.end();
        }
    }

    /**
     * The JSON configuration writer
     */
    private static class JSONConfigurationWriter extends ConfigurationWriter {

        JSONConfigurationWriter( final Writer delegatee ) {
            super( delegatee );
        }
    }

    /**
     * The HTML configuration writer outputs the status as an HTML snippet.
     */
    private static class HtmlConfigurationWriter extends ConfigurationWriter {

        // whether or not to filter "<" signs in the output
        private boolean doFilter;


        HtmlConfigurationWriter( final Writer delegatee ) {
            super( delegatee );
        }


        void enableFilter( final boolean doFilter ) {
            this.doFilter = doFilter;
        }

        // IE has an issue with white-space:pre in our case so, we write
        // <br/> instead of [CR]LF to get the line break. This also works
        // in other browsers.
        @Override
        public void println() {
            if ( doFilter ) {
                this.write('\n'); // write <br/>
            } else {
                super.println();
            }
        }

        // some VM implementation directly write in underlying stream, instead of
        // delegation to the write() method. So we need to override this, to make
        // sure, that everything is escaped correctly
        @Override
        public void print(final String str) {
            final char[] chars = str.toCharArray();
            write(chars, 0, chars.length);
        }


        private final char[] oneChar = new char[1];

        // always delegate to write(char[], int, int) otherwise in some VM
        // it cause endless cycle and StackOverflowError
        @Override
        public void write(final int character) {
            synchronized (oneChar) {
                oneChar[0] = (char) character;
                write(oneChar, 0, 1);
            }
        }

        // write the characters unmodified unless filtering is enabled in
        // which case the writeFiltered(String) method is called for filtering
        @Override
        public void write(char[] chars, int off, int len) {
            if (doFilter) {
                chars = this.escapeHtml(new String(chars, off, len)).toCharArray();
                off = 0;
                len = chars.length;
            }
            super.write(chars, off, len);
        }

        // write the string unmodified unless filtering is enabled in
        // which case the writeFiltered(String) method is called for filtering
        @Override
        public void write( final String string, final int off, final int len ) {
            write(string.toCharArray(), off, len);
        }

        /**
         * Escapes HTML special chars like: <>&\r\n and space
         *
         *
         * @param text the text to escape
         * @return the escaped text
         */
        private String escapeHtml(final String text) {
            final StringBuilder sb = new StringBuilder(text.length() * 4 / 3);
            char ch, oldch = '_';
            for (int i = 0; i < text.length(); i++) {
                switch (ch = text.charAt(i)) {
                    case '<':
                        sb.append("&lt;"); //$NON-NLS-1$
                        break;
                    case '>':
                        sb.append("&gt;"); //$NON-NLS-1$
                        break;
                    case '&':
                        sb.append("&amp;"); //$NON-NLS-1$
                        break;
                    case ' ':
                        sb.append("&nbsp;"); //$NON-NLS-1$
                        break;
                    case '\r':
                    case '\n':
                        if (oldch != '\r' && oldch != '\n') // don't add twice <br>
                            sb.append("<br/>\n"); //$NON-NLS-1$
                        break;
                    default:
                        sb.append(ch);
                }
                oldch = ch;
            }

            return sb.toString();
        }
    }

    /**
     * The plain text configuration writer outputs the status as plain text.
     */
    private static class PlainTextConfigurationWriter extends ConfigurationWriter {

        PlainTextConfigurationWriter( final Writer delegatee ) {
            super( delegatee );
        }

        @Override
        protected void title( final String title ) throws IOException {
            print( "*** " );
            print( title );
            println( ":" );
        }


        @Override
        protected void end() throws IOException {
            println();
        }
    }

    /**
     * The ZIP configuration writer creates a zip with
     * - txt output of a status printers (if supported)
     * - json output of a status printers (if supported)
     * - attachments from a status printer (if supported)
     */
    private static class ZipConfigurationWriter extends ConfigurationWriter {

        private final ZipOutputStream zip;

        private int counter;

        ZipConfigurationWriter( final ZipOutputStream zip ) {
            super( new OutputStreamWriter( zip ) );
            this.zip = zip;
        }

        private String getFormattedTitle(final String title) {
            return MessageFormat.format( "{0,number,000}-{1}", new Object[]
                    { new Integer( counter ), title } );
        }

        @Override
        protected void title( final String title ) throws IOException {
            counter++;

            final String name = getFormattedTitle(title).concat(".txt");

            final ZipEntry entry = new ZipEntry( name );
            zip.putNextEntry( entry );
        }

        @Override
        protected void end() throws IOException {
            flush();

            zip.closeEntry();
        }

        @Override
        public void printStatus(
                final PrinterMode mode,
                final StatusPrinterHandler handler)
        throws IOException {
            final String title = getFormattedTitle(handler.getTitle());
            if ( mode == PrinterMode.ZIP_FILE_TEXT ) {
                super.printStatus(mode, handler);
                handler.addAttachments(title.concat("/"), this.zip);
            } else {
                counter++;
                final String name = "json/".concat(title).concat(".json");

                final ZipEntry entry = new ZipEntry( name );
                zip.putNextEntry( entry );
                handler.print(PrinterMode.ZIP_FILE_JSON, this);
                flush();

                zip.closeEntry();
                if ( !handler.supports(PrinterMode.ZIP_FILE_TEXT) ) {
                    handler.addAttachments(title.concat("/"), this.zip);
                }
            }
        }
    }
}