// 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;
    }
    
    public abstract boolean isHostConnected();
    public abstract boolean isFrontEndAlive();

    @Override
    public long getAjaxSessionId() {
        return this.ajaxSessionId;
    }
    
    @Override
    public AjaxFIFOImageCache getAjaxImageCache() {
        return ajaxImageCache;
    }
    
    public Image getClientScaledImage(int width, int height) {
        FrameBufferCanvas canvas = getFrameBufferCavas();
        if(canvas != null)
            return canvas.getFrameBufferScaledImage(width, height);
        
        return null;
    }
    
    public abstract void sendClientRawKeyboardEvent(InputEventType event, int code, int modifiers);
    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_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);
    }
}
