// 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/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);
    }
}
