/*
 * 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.http.samples.cometd;

import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

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

import org.cometd.bayeux.server.BayeuxServer;
import org.cometd.bayeux.server.ConfigurableServerChannel;
import org.cometd.bayeux.server.LocalSession;
import org.cometd.bayeux.server.ServerChannel;
import org.cometd.bayeux.server.ServerMessage;

public class TimeServlet
    extends HttpServlet
{
    private static final long serialVersionUID = 1L;

    private enum SystemTopics {
        Time
    };

    private BayeuxServer bayeuxServer;
    private LocalSession session;
    private List<ServerChannel> channels;
    private Timer updateTimer;
    private SimpleDateFormat logDateFormat;
    private String html =
        "<html>\n" +
        "  <head>\n" +
        "    <title>System Information</title>\n" +
        "    <script type='text/javascript' src='/js/dojo/dojo.js'></script>\n" +
        "    <script type='text/javascript'>\n" +
        "      dojo.require('dojox.cometd');\n" +
        "dojo.addOnLoad(function()\n" + 
        "{\n" + 
        "    var cometd = dojox.cometd;\n" + 
        "\n" + 
        "    function _connectionEstablished()\n" + 
        "    {\n" + 
        "        dojo.byId('body').innerHTML += '<div>CometD Connection Established</div>';\n" + 
        "    }\n" + 
        "\n" + 
        "    function _connectionBroken()\n" + 
        "    {\n" + 
        "        dojo.byId('body').innerHTML += '<div>CometD Connection Broken</div>';\n" + 
        "    }\n" + 
        "\n" + 
        "    function _connectionClosed()\n" + 
        "    {\n" + 
        "        dojo.byId('body').innerHTML += '<div>CometD Connection Closed</div>';\n" + 
        "    }\n" + 
        "\n" + 
        "    // Function that manages the connection status with the Bayeux server\n" + 
        "    var _connected = false;\n" + 
        "    function _metaConnect(message)\n" + 
        "    {\n" + 
        "        if (cometd.isDisconnected())\n" + 
        "        {\n" + 
        "            _connected = false;\n" + 
        "            _connectionClosed();\n" + 
        "            return;\n" + 
        "        }\n" + 
        "\n" + 
        "        var wasConnected = _connected;\n" + 
        "        _connected = message.successful === true;\n" + 
        "        if (!wasConnected && _connected)\n" + 
        "        {\n" + 
        "            _connectionEstablished();\n" + 
        "        }\n" + 
        "        else if (wasConnected && !_connected)\n" + 
        "        {\n" + 
        "            _connectionBroken();\n" + 
        "        }\n" + 
        "    }\n" + 
        "\n" + 
        "    // Function invoked when first contacting the server and\n" + 
        "    // when the server has lost the state of this client\n" + 
        "    function _metaHandshake(handshake)\n" + 
        "    {\n" + 
        "        if (handshake.successful === true)\n" + 
        "        {\n" + 
        "            cometd.batch(function()\n" + 
        "            {\n" + 
        "                cometd.subscribe('/System/Time', function(message)\n" + 
        "                {\n" + 
        "                    dojo.byId('systemTime').innerHTML = '<div>' + message.data + '</div>';\n" + 
        "                });\n" + 
        "            });\n" + 
        "        }\n" + 
        "    }\n" + 
        "\n" + 
        "    // Disconnect when the page unloads\n" + 
        "    dojo.addOnUnload(function()\n" + 
        "    {\n" + 
        "        cometd.disconnect(true);\n" + 
        "    });\n" + 
        "\n" + 
        "    var cometURL = \"http://localhost:8080/system/cometd\";\n" + 
        "    cometd.configure({\n" + 
        "        url: cometURL,\n" + 
        "        logLevel: 'debug'\n" + 
        "    });\n" + 
        "\n" + 
        "    cometd.addListener('/meta/handshake', _metaHandshake);\n" + 
        "    cometd.addListener('/meta/connect', _metaConnect);\n" + 
        "\n" + 
        "    cometd.handshake();\n" + 
        "});\n" + 
        "    </script>\n" +
        "  </head>\n" +
        "  <body>\n" +
        "    <h2 id='systemTime'></h2>\n" +
        "  </body>\n" +
        "</html>\n";

    public TimeServlet(BayeuxServer bayeuxServer)
    {
        this.bayeuxServer = bayeuxServer;
        this.channels = new ArrayList<ServerChannel>();
        for (SystemTopics topic : SystemTopics.values()) {
        	boolean created = bayeuxServer.createIfAbsent("/System/" + topic, new ServerChannel.Initializer() {
				public void configureChannel(ConfigurableServerChannel channel) {
					channel.setPersistent(true);
				}
        	});
        	if (created) {
        		this.channels.add(topic.ordinal(), this.bayeuxServer.getChannel("/System/" + topic));
        	}
        }
        this.logDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
		this.updateTimer = new Timer("System.Time.ClientNotifier");
		this.updateTimer.scheduleAtFixedRate(new ClientNotifier(), 1000, 1000);
		this.session = bayeuxServer.newLocalSession(TimeServlet.class.getName());
		this.session.handshake();
    }

    @Override
    public void init(ServletConfig config)
        throws ServletException
    {
        doLog("Init with config [" + config + "]");
        super.init(config);
    }

    @Override
    public void destroy()
    {
        doLog("Destroyed servlet");
        this.updateTimer.cancel();
        this.session.disconnect();
        super.destroy();
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse res)
        throws ServletException, IOException
    {
        res.setContentType("text/html");
        PrintWriter out = res.getWriter();
        out.println(this.html);
    }

    private void doLog(String message)
    {
        System.out.println("## TimeServlet: " + message);
    }

    private class ClientNotifier
        extends TimerTask
    {

        public void run() {
            for (SystemTopics topic : SystemTopics.values()) {
                String topicData;
                switch (topic) {
                    case Time:
                        topicData = logDateFormat.format(new Date());
                        break;
                    default:
                        topicData = "unknown topic: " + topic.toString();
                }
                ServerMessage.Mutable message = bayeuxServer.newMessage();
                message.setChannel(channels.get(topic.ordinal()).getId());
                message.setData(topicData);
                channels.get(topic.ordinal()).publish(session, topicData, null);
            }
        }
    }

}
