// 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 com.cloud.consoleproxy;

import java.awt.Image;
import java.awt.Rectangle;
import java.util.List;

import org.apache.log4j.Logger;

import com.cloud.consoleproxy.util.TileInfo;
import com.cloud.consoleproxy.util.TileTracker;
import com.cloud.consoleproxy.vnc.FrameBufferCanvas;

/**
 *
 * an instance of specialized console protocol implementation, such as VNC or RDP
 *
 * It mainly implements the features needed by front-end AJAX viewer
 *
 */
public abstract class ConsoleProxyClientBase implements ConsoleProxyClient, ConsoleProxyClientListener {
    private static final Logger s_logger = Logger.getLogger(ConsoleProxyClientBase.class);

    private static int s_nextClientId = 0;
    protected int clientId = getNextClientId();

    protected long ajaxSessionId = 0;

    protected boolean dirtyFlag = false;
    protected Object tileDirtyEvent = new Object();
    protected TileTracker tracker;
    protected AjaxFIFOImageCache ajaxImageCache = new AjaxFIFOImageCache(2);

    protected ConsoleProxyClientParam clientParam;
    protected String clientToken;

    protected long createTime = System.currentTimeMillis();
    protected long lastFrontEndActivityTime = System.currentTimeMillis();

    protected boolean framebufferResized = false;
    protected int resizedFramebufferWidth;
    protected int resizedFramebufferHeight;

    public ConsoleProxyClientBase() {
        tracker = new TileTracker();
        tracker.initTracking(64, 64, 800, 600);
    }

    //
    // interface ConsoleProxyClient
    //
    @Override
    public int getClientId() {
        return clientId;
    }

    @Override
    public abstract boolean isHostConnected();

    @Override
    public abstract boolean isFrontEndAlive();

    @Override
    public long getAjaxSessionId() {
        return this.ajaxSessionId;
    }

    @Override
    public AjaxFIFOImageCache getAjaxImageCache() {
        return ajaxImageCache;
    }

    @Override
    public Image getClientScaledImage(int width, int height) {
        FrameBufferCanvas canvas = getFrameBufferCavas();
        if (canvas != null)
            return canvas.getFrameBufferScaledImage(width, height);

        return null;
    }

    @Override
    public abstract void sendClientRawKeyboardEvent(InputEventType event, int code, int modifiers);

    @Override
    public abstract void sendClientMouseEvent(InputEventType event, int x, int y, int code, int modifiers);

    @Override
    public long getClientCreateTime() {
        return createTime;
    }

    @Override
    public long getClientLastFrontEndActivityTime() {
        return lastFrontEndActivityTime;
    }

    @Override
    public String getClientHostAddress() {
        return clientParam.getClientHostAddress();
    }

    @Override
    public int getClientHostPort() {
        return clientParam.getClientHostPort();
    }

    @Override
    public String getClientHostPassword() {
        return clientParam.getClientHostPassword();
    }

    @Override
    public String getClientTag() {
        if (clientParam.getClientTag() != null)
            return clientParam.getClientTag();
        return "";
    }

    @Override
    public abstract void initClient(ConsoleProxyClientParam param);

    @Override
    public abstract void closeClient();

    //
    // interface FrameBufferEventListener
    //
    @Override
    public void onFramebufferSizeChange(int w, int h) {
        tracker.resize(w, h);

        synchronized (this) {
            framebufferResized = true;
            resizedFramebufferWidth = w;
            resizedFramebufferHeight = h;
        }

        signalTileDirtyEvent();
    }

    @Override
    public void onFramebufferUpdate(int x, int y, int w, int h) {
        if (s_logger.isTraceEnabled())
            s_logger.trace("Frame buffer update {" + x + "," + y + "," + w + "," + h + "}");
        tracker.invalidate(new Rectangle(x, y, w, h));

        signalTileDirtyEvent();
    }

    //
    // AJAX Image manipulation
    //
    public byte[] getFrameBufferJpeg() {
        FrameBufferCanvas canvas = getFrameBufferCavas();
        if (canvas != null)
            return canvas.getFrameBufferJpeg();

        return null;
    }

    public byte[] getTilesMergedJpeg(List<TileInfo> tileList, int tileWidth, int tileHeight) {
        FrameBufferCanvas canvas = getFrameBufferCavas();
        if (canvas != null)
            return canvas.getTilesMergedJpeg(tileList, tileWidth, tileHeight);
        return null;
    }

    private String prepareAjaxImage(List<TileInfo> tiles, boolean init) {
        byte[] imgBits;
        if (init)
            imgBits = getFrameBufferJpeg();
        else
            imgBits = getTilesMergedJpeg(tiles, tracker.getTileWidth(), tracker.getTileHeight());

        if (imgBits == null) {
            s_logger.warn("Unable to generate jpeg image");
        } else {
            if (s_logger.isTraceEnabled())
                s_logger.trace("Generated jpeg image size: " + imgBits.length);
        }

        int key = ajaxImageCache.putImage(imgBits);
        StringBuffer sb = new StringBuffer();
        sb.append("/ajaximg?token=").append(clientToken);
        sb.append("&key=").append(key);
        sb.append("&ts=").append(System.currentTimeMillis());

        return sb.toString();
    }

    private String prepareAjaxSession(boolean init) {
        if (init) {
            synchronized (this) {
                ajaxSessionId++;
            }
        }

        StringBuffer sb = new StringBuffer();
        sb.append("/ajax?token=").append(clientToken).append("&sess=").append(ajaxSessionId);
        return sb.toString();
    }

    @Override
    public String onAjaxClientKickoff() {
        return "onKickoff();";
    }

    private boolean waitForViewerReady() {
        long startTick = System.currentTimeMillis();
        while (System.currentTimeMillis() - startTick < 5000) {
            if (getFrameBufferCavas() != null)
                return true;

            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
            }
        }
        return false;
    }

    private String onAjaxClientConnectFailed() {
        return "<html><head></head><body><div id=\"main_panel\" tabindex=\"1\"><p>"
            + "Unable to start console session as connection is refused by the machine you are accessing" + "</p></div></body></html>";
    }

    @Override
    public String onAjaxClientStart(String title, List<String> languages, String guest) {
        updateFrontEndActivityTime();

        if (!waitForViewerReady())
            return onAjaxClientConnectFailed();

        synchronized (this) {
            ajaxSessionId++;
            framebufferResized = false;
        }

        int tileWidth = tracker.getTileWidth();
        int tileHeight = tracker.getTileHeight();
        int width = tracker.getTrackWidth();
        int height = tracker.getTrackHeight();

        if (s_logger.isTraceEnabled())
            s_logger.trace("Ajax client start, frame buffer w: " + width + ", " + height);

        /*
                int retry = 0;
                tracker.initCoverageTest();
                while(!tracker.hasFullCoverage() && retry < 10) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                    }
                    retry++;
                }
        */

        List<TileInfo> tiles = tracker.scan(true);
        String imgUrl = prepareAjaxImage(tiles, true);
        String updateUrl = prepareAjaxSession(true);

        StringBuffer sbTileSequence = new StringBuffer();
        int i = 0;
        for (TileInfo tile : tiles) {
            sbTileSequence.append("[").append(tile.getRow()).append(",").append(tile.getCol()).append("]");
            if (i < tiles.size() - 1)
                sbTileSequence.append(",");

            i++;
        }

        return getAjaxViewerPageContent(sbTileSequence.toString(), imgUrl, updateUrl, width, height, tileWidth, tileHeight, title,
            ConsoleProxy.keyboardType == ConsoleProxy.KEYBOARD_RAW, languages, guest);
    }

    private String getAjaxViewerPageContent(String tileSequence, String imgUrl, String updateUrl, int width, int height, int tileWidth, int tileHeight, String title,
        boolean rawKeyboard, List<String> languages, String guest) {

        StringBuffer sbLanguages = new StringBuffer("");
        if (languages != null) {
            for (String lang : languages) {
                if (sbLanguages.length() > 0) {
                    sbLanguages.append(",");
                }
                sbLanguages.append(lang);
            }
        }

        String[] content =
            new String[] {"<html>", "<head>", "<script type=\"text/javascript\" language=\"javascript\" src=\"/resource/js/jquery.js\"></script>",
                "<script type=\"text/javascript\" language=\"javascript\" src=\"/resource/js/cloud.logger.js\"></script>",
                "<script type=\"text/javascript\" language=\"javascript\" src=\"/resource/js/ajaxkeys.js\"></script>",
                "<script type=\"text/javascript\" language=\"javascript\" src=\"/resource/js/ajaxviewer.js\"></script>",
                "<script type=\"text/javascript\" language=\"javascript\" src=\"/resource/js/handler.js\"></script>",
                "<link rel=\"stylesheet\" type=\"text/css\" href=\"/resource/css/ajaxviewer.css\"></link>",
                "<link rel=\"stylesheet\" type=\"text/css\" href=\"/resource/css/logger.css\"></link>", "<title>" + title + "</title>", "</head>", "<body>",
                "<div id=\"toolbar\">", "<ul>", "<li>", "<a href=\"#\" cmd=\"sendCtrlAltDel\">",
                "<span><img align=\"left\" src=\"/resource/images/cad.gif\" alt=\"Ctrl-Alt-Del\" />Ctrl-Alt-Del</span>", "</a>", "</li>", "<li>",
                "<a href=\"#\" cmd=\"sendCtrlEsc\">",
                "<span><img align=\"left\" src=\"/resource/images/winlog.png\" alt=\"Ctrl-Esc\" style=\"width:16px;height:16px\"/>Ctrl-Esc</span>", "</a>", "</li>",

                "<li class=\"pulldown\">", "<a href=\"#\">",
                "<span><img align=\"left\" src=\"/resource/images/winlog.png\" alt=\"Keyboard\" style=\"width:16px;height:16px\"/>Keyboard</span>", "</a>", "<ul>",
                "<li><a href=\"#\" cmd=\"keyboard_us\"><span>Standard (US) keyboard</span></a></li>",
                "<li><a href=\"#\" cmd=\"keyboard_uk\"><span>UK keyboard</span></a></li>",
                "<li><a href=\"#\" cmd=\"keyboard_jp\"><span>Japanese keyboard</span></a></li>", "</ul>", "</li>", "</ul>",
                "<span id=\"light\" class=\"dark\" cmd=\"toggle_logwin\"></span>", "</div>", "<div id=\"main_panel\" tabindex=\"1\"></div>",
                "<script language=\"javascript\">", "var acceptLanguages = '" + sbLanguages.toString() + "';", "var tileMap = [ " + tileSequence + " ];",
                "var ajaxViewer = new AjaxViewer('main_panel', '" + imgUrl + "', '" + updateUrl + "', tileMap, ",
                String.valueOf(width) + ", " + String.valueOf(height) + ", " + String.valueOf(tileWidth) + ", " + String.valueOf(tileHeight) + ");",

                "$(function() {", "ajaxViewer.start();", "});",

                "</script>", "</body>", "</html>"};

        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < content.length; i++)
            sb.append(content[i]);

        return sb.toString();
    }

    public String onAjaxClientDisconnected() {
        return "onDisconnect();";
    }

    @Override
    public String onAjaxClientUpdate() {
        updateFrontEndActivityTime();
        if (!waitForViewerReady())
            return onAjaxClientDisconnected();

        synchronized (tileDirtyEvent) {
            if (!dirtyFlag) {
                try {
                    tileDirtyEvent.wait(3000);
                } catch (InterruptedException e) {
                }
            }
        }

        boolean doResize = false;
        synchronized (this) {
            if (framebufferResized) {
                framebufferResized = false;
                doResize = true;
            }
        }

        List<TileInfo> tiles;

        if (doResize)
            tiles = tracker.scan(true);
        else
            tiles = tracker.scan(false);
        dirtyFlag = false;

        String imgUrl = prepareAjaxImage(tiles, false);
        StringBuffer sbTileSequence = new StringBuffer();
        int i = 0;
        for (TileInfo tile : tiles) {
            sbTileSequence.append("[").append(tile.getRow()).append(",").append(tile.getCol()).append("]");
            if (i < tiles.size() - 1)
                sbTileSequence.append(",");

            i++;
        }

        return getAjaxViewerUpdatePageContent(sbTileSequence.toString(), imgUrl, doResize, resizedFramebufferWidth, resizedFramebufferHeight, tracker.getTileWidth(),
            tracker.getTileHeight());
    }

    private String getAjaxViewerUpdatePageContent(String tileSequence, String imgUrl, boolean resized, int width, int height, int tileWidth, int tileHeight) {

        String[] content =
            new String[] {"tileMap = [ " + tileSequence + " ];",
                resized ? "ajaxViewer.resize('main_panel', " + width + ", " + height + " , " + tileWidth + ", " + tileHeight + ");" : "",
                "ajaxViewer.refresh('" + imgUrl + "', tileMap, false);"};

        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < content.length; i++)
            sb.append(content[i]);

        return sb.toString();
    }

    //
    // Helpers
    //
    private synchronized static int getNextClientId() {
        return ++s_nextClientId;
    }

    private void signalTileDirtyEvent() {
        synchronized (tileDirtyEvent) {
            dirtyFlag = true;
            tileDirtyEvent.notifyAll();
        }
    }

    public void updateFrontEndActivityTime() {
        lastFrontEndActivityTime = System.currentTimeMillis();
    }

    protected abstract FrameBufferCanvas getFrameBufferCavas();

    public ConsoleProxyClientParam getClientParam() {
        return clientParam;
    }

    public void setClientParam(ConsoleProxyClientParam clientParam) {
        this.clientParam = clientParam;
        ConsoleProxyPasswordBasedEncryptor encryptor = new ConsoleProxyPasswordBasedEncryptor(ConsoleProxy.getEncryptorPassword());
        this.clientToken = encryptor.encryptObject(ConsoleProxyClientParam.class, clientParam);
    }
}
