/*
 * 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.event.impl.jobs.console;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLEncoder;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;

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

import org.apache.sling.api.request.ResponseUtil;
import org.apache.sling.discovery.InstanceDescription;
import org.apache.sling.event.impl.jobs.JobConsumerManager;
import org.apache.sling.event.impl.jobs.config.InternalQueueConfiguration;
import org.apache.sling.event.impl.jobs.config.JobManagerConfiguration;
import org.apache.sling.event.impl.jobs.config.TopologyCapabilities;
import org.apache.sling.event.jobs.Job;
import org.apache.sling.event.jobs.JobManager;
import org.apache.sling.event.jobs.Queue;
import org.apache.sling.event.jobs.QueueConfiguration;
import org.apache.sling.event.jobs.ScheduleInfo;
import org.apache.sling.event.jobs.ScheduledJobInfo;
import org.apache.sling.event.jobs.Statistics;
import org.apache.sling.event.jobs.TopicStatistics;
import org.apache.sling.event.jobs.consumer.JobConsumer;
import org.osgi.framework.Constants;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This is a web console plugin displaying the active queues, some statistics
 * and the configurations.
 * @since 3.0
 */
@Component(service={javax.servlet.Servlet.class, JobConsumer.class},
property = {
    Constants.SERVICE_VENDOR + "=The Apache Software Foundation",
    "felix.webconsole.label=slingevent",
    "felix.webconsole.title=Jobs",
    "felix.webconsole.category=Sling",
    JobConsumer.PROPERTY_TOPICS + "=sling/webconsole/test"
})
public class WebConsolePlugin extends HttpServlet implements JobConsumer {

    private static final String SLING_WEBCONSOLE_TEST_JOB_TOPIC = "sling/webconsole/test";

    private static final long serialVersionUID = -6983227434841706385L;

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Reference
    private JobManager jobManager;

    @Reference
    private JobManagerConfiguration configuration;

    @Reference
    private JobConsumerManager jobConsumerManager;

    private static final String PAR_QUEUE = "queue";

    private Queue getQueue(final HttpServletRequest req) {
        final String name = req.getParameter(PAR_QUEUE);
        if ( name != null ) {
            for(final Queue q : this.jobManager.getQueues()) {
                if ( name.equals(q.getName()) ) {
                    return q;
                }
            }
        }
        return null;
    }

    private String getQueueErrorMessage(final HttpServletRequest req, final String command) {
        final String name = req.getParameter(PAR_QUEUE);
        if ( name == null || name.length() == 0 ) {
            return "Queue parameter missing for opertation " + command;
        }
        return "Queue with name '" + name + "' not found for operation " + command;
    }

    @Override
    protected void doPost(final HttpServletRequest req, final HttpServletResponse resp)
    throws ServletException, IOException {
        String msg = null;
        final String cmd = req.getParameter("action");
        if ( "suspend".equals(cmd) ) {
            final Queue q = this.getQueue(req);
            if ( q != null ) {
                q.suspend();
            } else {
                msg = this.getQueueErrorMessage(req, "suspend");
            }
        } else if ( "resume".equals(cmd) ) {
            final Queue q = this.getQueue(req);
            if ( q != null ) {
                q.resume();
            } else {
                msg = this.getQueueErrorMessage(req, "resume");
            }
        } else if ( "reset".equals(cmd) ) {
            if ( req.getParameter(PAR_QUEUE) == null || req.getParameter(PAR_QUEUE).length() == 0 ) {
                this.jobManager.getStatistics().reset();
            } else {
                final Queue q = this.getQueue(req);
                if ( q != null ) {
                    q.getStatistics().reset();
                } else {
                    msg = this.getQueueErrorMessage(req, "reset");
                }
            }
        } else if ( "test".equals(cmd) ) {
            this.startTestJob();
        } else if ( "dropall".equals(cmd) ) {
            final Queue q = this.getQueue(req);
            if ( q != null ) {
                q.removeAll();
            } else {
                msg = this.getQueueErrorMessage(req, "drop all");
            }
        } else {
            msg = "Unknown command";
        }
        final String path = req.getContextPath() + req.getServletPath() + req.getPathInfo();
        final String redirectTo;
        if ( msg == null ) {
            redirectTo = path;
        } else {
            redirectTo = path + "?message=" + URLEncoder.encode(msg, "UTF-8");
        }
        resp.sendRedirect(resp.encodeRedirectURL(redirectTo));
    }

    private void startTestJob() {
        logger.info("Adding test job: {}", SLING_WEBCONSOLE_TEST_JOB_TOPIC);
        this.jobManager.addJob(SLING_WEBCONSOLE_TEST_JOB_TOPIC, null);
    }

    @Override
    protected void doGet(final HttpServletRequest req, final HttpServletResponse res)
     throws ServletException, IOException {
        final String msg = req.getParameter("message");
        final PrintWriter pw = res.getWriter();

        pw.println("<form method='POST' name='eventingcmd'>" +
        		     "<input type='hidden' name='action' value=''/>"+
                     "<input type='hidden' name='queue' value=''/>" +
                   "</form>");
        pw.println("<script type='text/javascript'>");
        pw.println("function eventingsubmit(action, queue) {" +
                   " document.forms['eventingcmd'].action.value = action;" +
                   " document.forms['eventingcmd'].queue.value = queue;" +
                   " document.forms['eventingcmd'].submit();" +
                   "} </script>");

        pw.printf("<p class='statline ui-state-highlight'>Apache Sling Job Handling%s%n</p>",
                msg != null ? " : " + ResponseUtil.escapeXml(msg) : "");
        pw.println("<div class='ui-widget-header ui-corner-top buttonGroup'>");
        pw.println("<span style='float: left; margin-left: 1em'>Apache Sling Job Handling: Overall Statistics</span>");
        this.printForm(pw, null, "Reset Stats", "reset");
        pw.println("</div>");

        pw.println("<table class='nicetable'><tbody>");
        String topics = this.jobConsumerManager.getTopics();
        if ( topics == null ) {
            topics = "";
        } else {
            final String[] allTopics = topics.split(",");
            final StringBuilder sb = new StringBuilder();
            boolean first = true;
            for(final String t : allTopics) {
                if ( first) {
                    first = false;
                } else {
                    sb.append("<br/>");
                }
                sb.append(ResponseUtil.escapeXml(t));
            }
            topics = sb.toString();
        }
        Statistics s = this.jobManager.getStatistics();
        pw.printf("<tr><td>Start Time</td><td>%s</td></tr>", formatDate(s.getStartTime()));
        pw.printf("<tr><td>Local topic consumers: </td><td>%s</td></tr>", topics);
        pw.printf("<tr><td>Last Activated</td><td>%s</td></tr>", formatDate(s.getLastActivatedJobTime()));
        pw.printf("<tr><td>Last Finished</td><td>%s</td></tr>", formatDate(s.getLastFinishedJobTime()));
        pw.printf("<tr><td>Queued Jobs</td><td>%s</td></tr>", s.getNumberOfQueuedJobs());
        pw.printf("<tr><td>Active Jobs</td><td>%s</td></tr>", s.getNumberOfActiveJobs());
        pw.printf("<tr><td>Jobs</td><td>%s</td></tr>", s.getNumberOfJobs());
        pw.printf("<tr><td>Finished Jobs</td><td>%s</td></tr>", s.getNumberOfFinishedJobs());
        pw.printf("<tr><td>Failed Jobs</td><td>%s</td></tr>", s.getNumberOfFailedJobs());
        pw.printf("<tr><td>Cancelled Jobs</td><td>%s</td></tr>", s.getNumberOfCancelledJobs());
        pw.printf("<tr><td>Processed Jobs</td><td>%s</td></tr>", s.getNumberOfProcessedJobs());
        pw.printf("<tr><td>Average Processing Time</td><td>%s</td></tr>", formatTime(s.getAverageProcessingTime()));
        pw.printf("<tr><td>Average Waiting Time</td><td>%s</td></tr>", formatTime(s.getAverageWaitingTime()));
        pw.println("</tbody></table>");
        pw.println("<br/>");

        pw.println("<table class='nicetable'><tbody>");
        pw.println("<tr><th colspan='2'>Topology Capabilities</th></tr>");
        final TopologyCapabilities cap = this.configuration.getTopologyCapabilities();
        if ( cap == null ) {
            pw.print("<tr><td colspan='2'>No topology information available !</td></tr>");
        } else {
            final Map<String, List<InstanceDescription>> instanceCaps = cap.getInstanceCapabilities();
            for(final Map.Entry<String, List<InstanceDescription>> entry : instanceCaps.entrySet()) {
                final StringBuilder sb = new StringBuilder();
                for(final InstanceDescription id : entry.getValue()) {
                    if ( sb.length() > 0 ) {
                        sb.append("<br/>");
                    }
                    if ( id.isLocal() ) {
                        sb.append("<b>local</b>");
                    } else {
                        sb.append(ResponseUtil.escapeXml(id.getSlingId()));
                    }
                }
                pw.printf("<tr><td>%s</td><td>%s</td></tr>", ResponseUtil.escapeXml(entry.getKey()), sb.toString());
            }
        }
        pw.println("</tbody></table>");
        pw.println("<br/>");

        pw.println("<p class='statline'>Scheduled Jobs</p>");
        pw.println("<table class='nicetable'><tbody>");
        final Collection<ScheduledJobInfo> infos = this.jobManager.getScheduledJobs();
        if ( infos.size() == 0 ) {
            pw.print("<tr><td colspan='5'>No jobs currently scheduled.</td></tr>");
        } else {
            pw.println("<tr><th>Schedule</th><th>Job Topic</th><th>Schedules</th></tr>");
            int index = 1;
            for(final ScheduledJobInfo info : infos) {
                pw.printf("<tr><td><b>%s</b></td><td>%s</td><td>",
                        String.valueOf(index), ResponseUtil.escapeXml(info.getJobTopic()));
                boolean first = true;
                for(final ScheduleInfo si : info.getSchedules() ) {
                    if ( !first ) {
                        pw.print("<br/>");
                    }
                    first = false;
                    switch ( si.getType() ) {
                    case YEARLY : pw.printf("YEARLY %s %s : %s:%s", si.getMonthOfYear(), si.getDayOfMonth(), si.getHourOfDay(), si.getMinuteOfHour());
                                  break;
                    case MONTHLY : pw.printf("MONTHLY %s : %s:%s", si.getDayOfMonth(), si.getHourOfDay(), si.getMinuteOfHour());
                                  break;
                    case WEEKLY : pw.printf("WEEKLY %s : %s:%s", si.getDayOfWeek(), si.getHourOfDay(), si.getMinuteOfHour());
                                  break;
                    case DAILY : pw.printf("DAILY %s:%s", si.getHourOfDay(), si.getMinuteOfHour());
                                 break;
                    case HOURLY : pw.printf("HOURLY %s", si.getMinuteOfHour());
                                 break;
                    case CRON : pw.printf("CRON %s", ResponseUtil.escapeXml(si.getExpression()));
                                  break;
                    default : pw.printf("AT %s", si.getAt());
                    }
                }
                pw.print("</td></tr>");
                index++;
            }
        }
        pw.println("</tbody></table>");
        pw.println("<br/>");

        boolean isEmpty = true;
        for(final Queue q : this.jobManager.getQueues()) {
            isEmpty = false;
            final String queueName = q.getName();
            pw.println("<div class='ui-widget-header ui-corner-top buttonGroup'>");
            pw.printf("<span style='float: left; margin-left: 1em'>Active JobQueue: %s %s</span>", ResponseUtil.escapeXml(queueName),
                    q.isSuspended() ? "(SUSPENDED)" : "");
            this.printForm(pw, queueName, "Reset Stats", "reset");
            if ( q.isSuspended() ) {
                this.printForm(pw, queueName, "Resume", "resume");
            } else {
                this.printForm(pw, queueName, "Suspend", "suspend");
            }
            this.printForm(pw, queueName, "Test", "test");
            this.printForm(pw, queueName, "Drop All", "dropall");
            pw.println("</div>");
            pw.println("<table class='nicetable'><tbody>");

            s = q.getStatistics();
            final QueueConfiguration c = q.getConfiguration();
            pw.println("<tr><th colspan='2'>Statistics</th><th colspan='2'>Configuration</th></tr>");
            pw.printf("<tr><td>Start Time</td><td>%s</td><td>Type</td><td>%s</td></tr>", formatDate(s.getStartTime()), formatType(c.getType()));
            pw.printf("<tr><td>Last Activated</td><td>%s</td><td>Topics</td><td>%s</td></tr>", formatDate(s.getLastActivatedJobTime()), formatArray(c.getTopics()));
            pw.printf("<tr><td>Last Finished</td><td>%s</td><td>Max Parallel</td><td>%s</td></tr>", formatDate(s.getLastFinishedJobTime()), c.getMaxParallel());
            pw.printf("<tr><td>Queued Jobs</td><td>%s</td><td>Max Retries</td><td>%s</td></tr>", s.getNumberOfQueuedJobs(), c.getMaxRetries());
            pw.printf("<tr><td>Active Jobs</td><td>%s</td><td>Retry Delay</td><td>%s ms</td></tr>", s.getNumberOfActiveJobs(), c.getRetryDelayInMs());
            pw.printf("<tr><td>Jobs</td><td>%s</td><td>Priority</td><td>%s</td></tr>", s.getNumberOfJobs(), c.getThreadPriority());
            pw.printf("<tr><td>Finished Jobs</td><td>%s</td><td colspan='2'>&nbsp</td></tr>", s.getNumberOfFinishedJobs());
            pw.printf("<tr><td>Failed Jobs</td><td>%s</td><td colspan='2'>&nbsp</td></tr>", s.getNumberOfFailedJobs());
            pw.printf("<tr><td>Cancelled Jobs</td><td>%s</td><td colspan='2'>&nbsp</td></tr>", s.getNumberOfCancelledJobs());
            pw.printf("<tr><td>Processed Jobs</td><td>%s</td><td colspan='2'>&nbsp</td></tr>", s.getNumberOfProcessedJobs());
            pw.printf("<tr><td>Average Processing Time</td><td>%s</td><td colspan='2'>&nbsp</td></tr>", formatTime(s.getAverageProcessingTime()));
            pw.printf("<tr><td>Average Waiting Time</td><td>%s</td><td colspan='2'>&nbsp</td></tr>", formatTime(s.getAverageWaitingTime()));
            pw.printf("<tr><td>Status Info</td><td colspan='3'>%s</td></tr>", ResponseUtil.escapeXml(q.getStateInfo()));
            pw.println("</tbody></table>");
            pw.println("<br/>");
        }
        if ( isEmpty ) {
            pw.println("<p>No active queues.</p>");
            pw.println("<br/>");
        }

        for(final TopicStatistics ts : this.jobManager.getTopicStatistics()) {
            pw.println("<table class='nicetable'><tbody>");
            pw.printf("<tr><th colspan='2'>Topic Statistics: %s</th></tr>", ResponseUtil.escapeXml(ts.getTopic()));

            pw.printf("<tr><td>Last Activated</td><td>%s</td></tr>", formatDate(ts.getLastActivatedJobTime()));
            pw.printf("<tr><td>Last Finished</td><td>%s</td></tr>", formatDate(ts.getLastFinishedJobTime()));
            pw.printf("<tr><td>Finished Jobs</td><td>%s</td></tr>", ts.getNumberOfFinishedJobs());
            pw.printf("<tr><td>Failed Jobs</td><td>%s</td></tr>", ts.getNumberOfFailedJobs());
            pw.printf("<tr><td>Cancelled Jobs</td><td>%s</td></tr>", ts.getNumberOfCancelledJobs());
            pw.printf("<tr><td>Processed Jobs</td><td>%s</td></tr>", ts.getNumberOfProcessedJobs());
            pw.printf("<tr><td>Average Processing Time</td><td>%s</td></tr>", formatTime(ts.getAverageProcessingTime()));
            pw.printf("<tr><td>Average Waiting Time</td><td>%s</td></tr>", formatTime(ts.getAverageWaitingTime()));
            pw.println("</tbody></table>");
            pw.println("<br/>");
        }

        pw.println("<p class='statline'>Apache Sling Job Handling - Job Queue Configurations</p>");
        this.printQueueConfiguration(req, pw, this.configuration.getQueueConfigurationManager().getMainQueueConfiguration());
        final InternalQueueConfiguration[] configs = this.configuration.getQueueConfigurationManager().getConfigurations();
        for(final InternalQueueConfiguration c : configs ) {
            this.printQueueConfiguration(req, pw, c);
        }
    }

    private void printQueueConfiguration(final HttpServletRequest req, final PrintWriter pw, final InternalQueueConfiguration c) {
        pw.println("<div class='ui-widget-header ui-corner-top buttonGroup'>");
        pw.printf("<span style='float: left; margin-left: 1em'>Job Queue Configuration: %s</span>%n",
                ResponseUtil.escapeXml(c.getName()));
        pw.printf("<button id='edit' class='ui-state-default ui-corner-all' onclick='javascript:window.location=\"%s%s/configMgr/%s\";'>Edit</button>",
                req.getContextPath(), req.getServletPath(), c.getPid());
        this.printForm(pw, c.getName(), "Test", "test");

        pw.println("</div>");
        pw.println("<table class='nicetable'><tbody>");
        pw.println("<tr><th colspan='2'>Configuration</th></tr>");
        pw.printf("<tr><td>Valid</td><td>%s</td></tr>", c.isValid());
        pw.printf("<tr><td>Type</td><td>%s</td></tr>", formatType(c.getType()));
        pw.printf("<tr><td>Topics</td><td>%s</td></tr>", formatArray(c.getTopics()));
        pw.printf("<tr><td>Max Parallel</td><td>%s</td></tr>", c.getMaxParallel());
        pw.printf("<tr><td>Max Retries</td><td>%s</td></tr>", c.getMaxRetries());
        pw.printf("<tr><td>Retry Delay</td><td>%s ms</td></tr>", c.getRetryDelayInMs());
        pw.printf("<tr><td>Priority</td><td>%s</td></tr>", c.getThreadPriority());
        pw.printf("<tr><td>Ranking</td><td>%s</td></tr>", c.getRanking());

        pw.println("</tbody></table>");
        pw.println("<br/>");
    }

    /**
     * Format an array for html rendering.
     */
    private String formatArray(final String[] array) {
        if ( array == null || array.length == 0 ) {
            return "";
        }
        final StringBuilder sb = new StringBuilder();
        boolean first = true;
        for(final String s : array ) {
            if ( !first ) {
                sb.append('\n');
            }
            first = false;
            sb.append(s);
        }
        return ResponseUtil.escapeXml(sb.toString());
    }

    private String formatType(final QueueConfiguration.Type type) {
        switch ( type ) {
            case ORDERED : return "Ordered";
            case TOPIC_ROUND_ROBIN : return "Topic Round Robin";
            case UNORDERED : return "Parallel";
        }
        return type.toString();
    }
    /** Default date format used. */
    private final DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss:SSS yyyy-MMM-dd");

    /**
     * Format a date
     */
    private synchronized String formatDate(final long time) {
        if ( time == -1 ) {
            return "-";
        }
        final Date d = new Date(time);
        return dateFormat.format(d);
    }

    /**
     * Format time (= duration)
     */
    private String formatTime(final long time) {
        if ( time == 0 ) {
            return "-";
        }
        if ( time < 1000 ) {
            return time + " ms";
        } else if ( time < 1000 * 60 ) {
            return time / 1000 + " secs";
        }
        final long min = time / 1000 / 60;
        final long secs = (time - min * 1000 * 60);
        return min + " min " + secs / 1000 + " secs";
    }

    private void printForm(final PrintWriter pw,
            final String qeueName,
            final String buttonLabel,
            final String cmd) {
        pw.printf("<button class='ui-state-default ui-corner-all' onclick='javascript:eventingsubmit(\"%s\", \"%s\");'>" +
                "%s</button>", ResponseUtil.escapeXml(cmd), (qeueName != null ? ResponseUtil.escapeXml(qeueName) : ""), ResponseUtil.escapeXml(buttonLabel));
    }

    @Override
    public JobResult process(final Job job) {
        logger.info("Received test job {}", job.getTopic());
        return JobResult.OK;
    }
}
