/**
 * 
 * This software is licensed under the GNU General Public License v3 or later.
 * 
 * It is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 */

package com.cloud.consoleproxy;


import java.awt.Container;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.GZIPOutputStream;

import org.apache.log4j.Logger;

import com.cloud.console.AuthenticationException;
import com.cloud.console.ConsoleCanvas;
import com.cloud.console.ConsoleCanvas2;
import com.cloud.console.ITileScanListener;
import com.cloud.console.Region;
import com.cloud.console.RfbProto;
import com.cloud.console.RfbProtoAdapter;
import com.cloud.console.RfbViewer;
import com.cloud.console.TileInfo;
import com.cloud.console.TileTracker;

public class ConsoleProxyViewer implements java.lang.Runnable, RfbViewer, RfbProtoAdapter, ITileScanListener {
	private static final Logger s_logger = Logger.getLogger(ConsoleProxyViewer.class);
	
	public final static int STATUS_ERROR = -1;
	public final static int STATUS_UNINITIALIZED = 0;
	public final static int STATUS_CONNECTING = 1;
	public final static int STATUS_INITIALIZING = 2;
	public final static int STATUS_NORMAL_OPERATION = 3;
	public final static int STATUS_AUTHENTICATION_FAILURE = 100;
	
	public final static int SHIFT_KEY_MASK = 64;
	public final static int CTRL_KEY_MASK = 128;
	public final static int META_KEY_MASK = 256;
	public final static int ALT_KEY_MASK = 512;
	
	int id = getNextId();
	boolean compressServerMessage = false;
	long createTime = System.currentTimeMillis();
	long lastUsedTime = System.currentTimeMillis();
	int status;
	boolean dropMe = false;
	boolean viewerInReuse = false; 
	
	String host;
	int port;
	String tag = "";
	
	RfbProto rfb;
	Thread rfbThread;
	OutputStream clientStream;
	String clientStreamInfo;
	String passwordParam;
	
	ViewerOptions options;
	Frame vncFrame;
	ConsoleCanvas vc;
	Container vncContainer;
	
	boolean ajaxViewer = false;
	long ajaxSessionId = 0;
	TileTracker tracker;
	Object tileDirtyEvent;
	boolean dirtyFlag = false;
	boolean justCreated = true;
	AjaxFIFOImageCache ajaxImageCache = new AjaxFIFOImageCache(2);
	
	String cursorUpdatesDef;
	String eightBitColorsDef;
	
	int deferScreenUpdates;
	int deferCursorUpdates;
	int deferUpdateRequests;
	
	int[] encodingsSaved;
	int nEncodingsSaved;

	boolean framebufferResized = false;
	int resizedFramebufferWidth;
	int resizedFramebufferHeight;
	
	boolean cursorMoved = false;
	int lastCursorPosX;
	int lastCursorPosY;
	
	boolean cursorShapeChanged = false;
	int lastCursorShapeEncodingType;
	int lastCursorShapeHotX;
	int lastCursorShapeHotY;
	int lastCursorShapeWidth;
	int lastCursorShapeHeight;
	byte[] lastCursorShapeData;
	
	static int id_count = 1;
	synchronized static int getNextId() {
		return id_count++;
	}

	public void init() {
		initProxy();
	}
	
	private void initProxy() {
		options = new ViewerOptions();
		options.viewOnly = true;

		cursorUpdatesDef = null;
		eightBitColorsDef = null;
		
		tracker = new TileTracker();
		tracker.initTracking(64, 64, 800, 600);

		if(rfbThread != null) {
			if(rfbThread.isAlive()) {
				dropMe = true;
				viewerInReuse = true;
				if(rfb != null)
					rfb.close();
				
				try {
					rfbThread.join();
				} catch (InterruptedException e) {
					s_logger.warn("InterruptedException while waiting for RFB thread to exit");
				}
				viewerInReuse = false;
			}
		}
		
		dropMe = false;
		rfbThread = new Thread(this);
		rfbThread.setName("RFB Thread " + rfbThread.getId() + " >" + host + ":" + port);
		rfbThread.start();

		tileDirtyEvent = new Object();
	}
	
	public synchronized boolean justCreated() {
		if(justCreated) {
			justCreated = false;
			return true;
		}
		return false;
	}
	
	public boolean isDropped() {
		return dropMe;
	}
	
	public void run() {
		createCanvas(0, 0);

		int retries = 0;
		while (!dropMe) {
			try {
				s_logger.info("Connecting to VNC server");
				status = STATUS_CONNECTING;
				connectAndAuthenticate();
				retries = 0; // reset the retry count
				status = STATUS_INITIALIZING;
				doProtocolInitialisation();
				vc.rfb = rfb;
				vc.setPixelFormat();

				// if we have a client current connected, when we have reconnected to the server and
				// received a new ServerInit info (in doProtocolInitialisation()), we will
				// convert it into frame buffer size change to make sure following on updates
				// don't fall out of range
				//
				if(clientStream != null) {
					// 128 bytes will be enough for this single PDU
					s_logger.info("Send init framebuffer size (" + rfb.framebufferWidth + ", " + rfb.framebufferHeight + ")");
					
					ByteArrayOutputStream bos = new ByteArrayOutputStream(128);
					try {
						vc.encodeFramebufferResize(rfb.framebufferWidth, rfb.framebufferHeight, bos);
					} catch(IOException e) {
					}
					writeToClientStream(bos.toByteArray());
				}
				
				vc.rfb.writeFramebufferUpdateRequest(0, 0,
						vc.rfb.framebufferWidth, vc.rfb.framebufferHeight,
						true);
				status = STATUS_NORMAL_OPERATION;
				vc.processNormalProtocol();
			} catch (AuthenticationException e) {
				status = STATUS_AUTHENTICATION_FAILURE;
				String msg = e.getMessage();
				s_logger.warn("Authentication exception, msg: " + msg + "sid: " + this.passwordParam);
			} catch (Exception e) {
				status = STATUS_ERROR;
				s_logger.error("Unexpected exception ", e);
			} finally {
				// String oldName = Thread.currentThread().getName();
				encodingsSaved = null;
				nEncodingsSaved = 0;
				
				s_logger.info("Close current RFB");
				synchronized (this) {
					if (rfb != null) {
						rfb.close();
					}
				}
			}
			if (dropMe) {
				break;
			}
			if (status == STATUS_AUTHENTICATION_FAILURE) {
				break;
			} else {
				retries++;
				if(retries > ConsoleProxy.reconnectMaxRetry) {
					s_logger.info("Exception caught, retry has reached to maximum : " + retries + ", will give up and disconnect client");
					break;
				}
				
				s_logger.info("Exception caught, retrying in 1 second, current retry:" + retries);
				
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					// ignored
				}
			}
		}
		
		// make sure we remove it from the management map upon main thread termination
		dropMe = true;
		
		// if we are reusing the viewer object, we shouldn't remove it from the map
		// this can also prevent deadlock in initProxy() while initProxy tries to join
		// the thread, as initProxy() is called with ConsoleProxy.connectionMap being locked
		// while CoonsoleProxy.removeViewer() here will attempt to lock it from another thread
		if(!viewerInReuse)		
			ConsoleProxy.removeViewer(this);
		s_logger.info("RFB thread terminating");
	}
	
	void connectAndAuthenticate() throws Exception {
		s_logger.info("Initializing...");
		
		s_logger.info("Ensure ip route towards host " + host);
		ConsoleProxy.ensureRoute(host);		
		
		s_logger.info("Connecting to " + host + ", port " + port + "...");
		rfb = new RfbProto(host, port, this);
		s_logger.info("Connected to server");

		rfb.readVersionMsg();
		s_logger.info("RFB server supports protocol version "
				+ rfb.serverMajor + "." + rfb.serverMinor);

		rfb.writeVersionMsg();
		s_logger.info("Using RFB protocol version " + rfb.clientMajor
				+ "." + rfb.clientMinor);

		int secType = rfb.negotiateSecurity();
		int authType;
		if (secType == RfbProto.SecTypeTight) {
			s_logger.info("Enabling TightVNC protocol extensions");
			rfb.initCapabilities();
			rfb.setupTunneling();
			authType = rfb.negotiateAuthenticationTight();
		} else {
			authType = secType;
		}

		switch (authType) {
		case RfbProto.AuthNone:
			s_logger.info("No authentication needed");
			rfb.authenticateNone();
			break;
		case RfbProto.AuthVNC:
			s_logger.info("Performing standard VNC authentication");
			if (passwordParam != null) {
				rfb.authenticateVNC(passwordParam);
			} else {
				throw new AuthenticationException("Bad password");
			}
			break;
		default:
			throw new Exception("Unknown authentication scheme " + authType);
		}
	}
	
	static void authenticationExternally(String host, String port, String tag, String sid, String ticket) throws AuthenticationException {
/*		
		if(ConsoleProxy.management_host != null) {
			try {
				boolean success = false;
				URL url = new URL(ConsoleProxy.management_host + "/console?cmd=auth&vm=" + getTag() + "&sid=" + passwordParam);
				
				URLConnection conn = url.openConnection();
				
				// setting TIMEOUTs to avoid possible waiting until death situations
				conn.setConnectTimeout(5000);
				conn.setReadTimeout(5000);
				
		        BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
		        String inputLine;
		        if ((inputLine = in.readLine()) != null) { 
		            if(inputLine.equals("success"))
		            	success = true;
		        }
		        in.close();
		        
		        if(!success) {
		        	if(s_logger.isInfoEnabled())
		        		s_logger.info("External authenticator failed authencation request for vm " + getTag() + " with sid " + passwordParam);
		        	
					throw new AuthenticationException("Unable to contact external authentication source " + ConsoleProxy.management_host);
		        }
			} catch (MalformedURLException e) {
				s_logger.error("Unexpected exception " + e.getMessage(), e);
			} catch(IOException e) {
				s_logger.error("Unable to contact external authentication source due to " + e.getMessage(), e);
				throw new AuthenticationException("Unable to contact external authentication source " + ConsoleProxy.management_host);
			}
		} else {
			s_logger.warn("No external authentication source being setup.");
		}
*/
		if(!ConsoleProxy.authenticateConsoleAccess(host, port, tag, sid, ticket)) {
    		s_logger.warn("External authenticator failed authencation request for vm " + tag + " with sid " + sid);
        	
			throw new AuthenticationException("External authenticator failed request for vm " + tag + " with sid " + sid);
		}
	}
	
	void doProtocolInitialisation() throws IOException {
		rfb.writeClientInit();
		rfb.readServerInit();
		setEncodings();
	}
	
	void setEncodings() {
		setEncodings(false);
	}
	
	void setEncodings(boolean autoSelectOnly) {
		if (options == null || rfb == null || !rfb.inNormalProtocol)
			return;

		options.preferredEncoding = RfbProto.EncodingHextile;
		
		int preferredEncoding = options.preferredEncoding;
		if (preferredEncoding == -1) {
			long kbitsPerSecond = rfb.kbitsPerSecond();
			if (nEncodingsSaved < 1) {
				// Choose Tight or ZRLE encoding for the very first update.
				// Logger.log(Logger.INFO, "Using Tight/ZRLE encodings");
				preferredEncoding = RfbProto.EncodingTight;
			} else if (kbitsPerSecond > 2000
					&& encodingsSaved[0] != RfbProto.EncodingHextile) {
				// Switch to Hextile if the connection speed is above 2Mbps.
				s_logger.info("Throughput " + kbitsPerSecond
						+ " kbit/s - changing to Hextile encoding");
				preferredEncoding = RfbProto.EncodingHextile;
			} else if (kbitsPerSecond < 1000
					&& encodingsSaved[0] != RfbProto.EncodingTight) {
				// Switch to Tight/ZRLE if the connection speed is below 1Mbps.
				s_logger.info("Throughput " + kbitsPerSecond
						+ " kbit/s - changing to Tight/ZRLE encodings");
				preferredEncoding = RfbProto.EncodingTight;
			} else {
				// Don't change the encoder.
				if (autoSelectOnly)
					return;
				preferredEncoding = encodingsSaved[0];
			}
		} else {
			// Auto encoder selection is not enabled.
			if (autoSelectOnly)
				return;
		}

		int[] encodings = new int[20];
		int nEncodings = 0;

		encodings[nEncodings++] = preferredEncoding;
		if (options.useCopyRect) {
			encodings[nEncodings++] = RfbProto.EncodingCopyRect;
		}

		if (preferredEncoding != RfbProto.EncodingTight) {
			encodings[nEncodings++] = RfbProto.EncodingTight;
		}
		if (preferredEncoding != RfbProto.EncodingZRLE) {
			encodings[nEncodings++] = RfbProto.EncodingZRLE;
		}
		if (preferredEncoding != RfbProto.EncodingHextile) {
			encodings[nEncodings++] = RfbProto.EncodingHextile;
		}
		if (preferredEncoding != RfbProto.EncodingZlib) {
			encodings[nEncodings++] = RfbProto.EncodingZlib;
		}
		if (preferredEncoding != RfbProto.EncodingCoRRE) {
			encodings[nEncodings++] = RfbProto.EncodingCoRRE;
		}
		if (preferredEncoding != RfbProto.EncodingRRE) {
			encodings[nEncodings++] = RfbProto.EncodingRRE;
		}

		if (options.compressLevel >= 0 && options.compressLevel <= 9) {
			encodings[nEncodings++] = RfbProto.EncodingCompressLevel0
					+ options.compressLevel;
		}
		if (options.jpegQuality >= 0 && options.jpegQuality <= 9) {
			encodings[nEncodings++] = RfbProto.EncodingQualityLevel0
					+ options.jpegQuality;
		}

		if (options.requestCursorUpdates) {
			encodings[nEncodings++] = RfbProto.EncodingXCursor;
			encodings[nEncodings++] = RfbProto.EncodingRichCursor;
			if (!options.ignoreCursorUpdates)
				encodings[nEncodings++] = RfbProto.EncodingPointerPos;
		}

		encodings[nEncodings++] = RfbProto.EncodingLastRect;
		encodings[nEncodings++] = RfbProto.EncodingNewFBSize;

		boolean encodingsWereChanged = false;
		if (nEncodings != nEncodingsSaved) {
			encodingsWereChanged = true;
		} else {
			for (int i = 0; i < nEncodings; i++) {
				if (encodings[i] != encodingsSaved[i]) {
					encodingsWereChanged = true;
					break;
				}
			}
		}

		if (encodingsWereChanged) {
			try {
				rfb.writeSetEncodings(encodings, nEncodings);
				if (vc != null) {
					vc.softCursorFree();
				}
			} catch (Exception e) {
				s_logger.error(e.toString(), e);
			}
			encodingsSaved = encodings;
			nEncodingsSaved = nEncodings;
		}
	}

	protected void startRecording() throws IOException {
	}
	
	protected void stopRecording() throws IOException {
	}
	
	void createCanvas(int maxWidth, int maxHeight) {
		vc = new ConsoleCanvas2(this, maxWidth, maxHeight);
		
	    if (!options.viewOnly)
	        vc.enableInput(true);
	}
	
	synchronized void writeToClientStream(byte[] bs) {
		// writeToClientStream swallows exceptions to make sure problems writing
		// to client stream do not impact the main loop
		if (clientStream != null) {
			try {
				lastUsedTime = System.currentTimeMillis();
				synchronized (clientStream) {
					clientStream.write(bs);
					clientStream.flush();
				}
			} catch (IOException e) {
				if(s_logger.isDebugEnabled()) {
					s_logger.debug("Writing to client stream failed, reason: " + e.getMessage());
				}
				try {
					clientStream.close();
				} catch (IOException ioe){
					// ignore
				}
				clientStream = null;
				clientStreamInfo = null;
			  }
		}
	}
	
	//
	// Implement RfbViewer interface
	//
	public boolean isProxy() {
		return true;
	}
	
	public boolean hasClientConnection() {
		// always return false if the viewer is AJAX viewer
		if(ajaxViewer)
			return false;
		
		return clientStream != null;
	}
	
	public RfbProto getRfb() {
		return rfb;
	}
	
	public Dimension getScreenSize() {
		return (new Frame()).getToolkit().getScreenSize();
		// return vncFrame.getToolkit().getScreenSize();
	}
	
	public Dimension getFrameSize() {
		// return vncFrame.getSize();
		return getScreenSize();
	}
	
	public int getScalingFactor() {
		return options.scalingFactor;
	}
	
	public int getCursorScaleFactor() {
		return options.scaleCursor;
	}
	
	public boolean ignoreCursorUpdate() {
		return options.ignoreCursorUpdates;
	}
	
	public int getDeferCursorUpdateTimeout() {
		return 0;
		// return deferCursorUpdates; 
	}
	
	public int getDeferScreenUpdateTimeout() {
		return 0;
		// return deferScreenUpdates;
	}
	
	public int getDeferUpdateRequestTimeout() {
		return 0;
		//return deferUpdateRequests;
	}
	
	public int setPixelFormat(RfbProto rfb) throws IOException {
		if (options.eightBitColors) {
	        rfb.writeSetPixelFormat(8, 8, false, true, 7, 7, 3, 0, 3, 6);
	        return 1;
		} else {
			rfb.writeSetPixelFormat(32, 24, false, true, 255, 255, 255, 16, 8, 0);
			return 4;
		}
	}
	
	public void onInputEnabled(boolean enable) {
		// do nothing in proxy viewer
	}
	
	public void onFramebufferSizeChange(int w, int h) {
		tracker.resize(vc.scaledWidth, vc.scaledHeight);

		synchronized(this) {
			framebufferResized = true;
			resizedFramebufferWidth = w;
			resizedFramebufferHeight = h;
		}
		
		signalTileDirtyEvent();
	}
	
	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();
	}
	
	public void onFramebufferCursorMove(int x, int y) {
		synchronized(this) {
			cursorMoved = true;
			lastCursorPosX = x;
			lastCursorPosY = y;
		}
		
		signalTileDirtyEvent();
	}
	
	public void onFramebufferCursorShapeChange(int encodingType,
		    int xhot, int yhot, int width, int height, byte[] cursorData) {

		synchronized(this) {
			cursorShapeChanged = true;
			
			lastCursorShapeEncodingType = encodingType;
			lastCursorShapeHotX = xhot;
			lastCursorShapeHotY = yhot;
			lastCursorShapeWidth = width;
			lastCursorShapeHeight = height;
			lastCursorShapeData = cursorData;
		}
		
		signalTileDirtyEvent();
	}
	
	public void onDesktopResize() {
		if(vncFrame != null)
			vncFrame.pack();
	}
	
	public void onFrameResize(Dimension newSize) {
		if(vncFrame != null)
			vncFrame.setSize(newSize);
	}
	
	public void onDisconnectMessage() {
		// do nothing in viewer mode
	}
	
	public void onBellMessage() {
		Toolkit.getDefaultToolkit().beep();
	}
	
	public void onPreProtocolProcess(byte[] bs) throws IOException {
		
		if(s_logger.isTraceEnabled())
			s_logger.trace("Send " + (bs != null ? bs.length  : 0) + " bytes (original) to client");

		if (!ajaxViewer && bs != null && clientStream != null) {
			if(s_logger.isInfoEnabled())
				s_logger.info("getSplit got " + bs.length + " bytes");
			if (compressServerMessage && bs.length > 10000) {
				ByteArrayOutputStream bos = new ByteArrayOutputStream(256000);
				GZIPOutputStream gos = new GZIPOutputStream(bos, 65536);
				gos.write(bs);
				gos.finish();
				byte[] nbs = bos.toByteArray();
				gos.close();
				int n = nbs.length;
				
				if(s_logger.isInfoEnabled())
					s_logger.info("Compressed " + bs.length + "=>" + n);
				
				byte[] b = new byte[6];
				b[0] = (byte) 250;
				b[1] = 2;
				b[2] = (byte) ((n >> 24) & 0xff);
				b[3] = (byte) ((n >> 16) & 0xff);
				b[4] = (byte) ((n >> 8) & 0xff);
				b[5] = (byte) (n & 0xff);
				
				// make sure two seperated writes completed atomically
				synchronized(clientStream) {
					writeToClientStream(b);
					writeToClientStream(nbs);
				}
			} else {
				if(s_logger.isInfoEnabled())
					s_logger.info("Send uncompressed " + bs.length + " bytes to client");
				
				writeToClientStream(bs);
			}
		} else {
			if(s_logger.isTraceEnabled())
				s_logger.trace("Client is not connected, ignore forwarding " + (bs != null ? bs.length : 0) + " bytes to client");
		}
		
	    rfb.sis.setSplit();
	}
	
	public boolean onPostFrameBufferUpdateProcess(boolean cursorPosReceived) throws IOException {
		boolean fullUpdateNeeded = false;
		
		// Defer framebuffer update request if necessary. But wake up
		// immediately on keyboard or mouse event. Also, don't sleep
		// if there is some data to receive, or if the last update
		// included a PointerPos message.
		if (deferUpdateRequests > 0 && rfb.is.available() == 0 && !cursorPosReceived) {
		  synchronized(vc.rfb) {
		    try {
		      vc.rfb.wait(deferUpdateRequests);
		    } catch (InterruptedException e) {
		    }
		  }
		}

		// Before requesting framebuffer update, check if the pixel
		// format should be changed. If it should, request full update
		// instead of an incremental one.
		if (options.eightBitColors != (vc.bytesPixel == 1)) {
			vc.setPixelFormat();
			fullUpdateNeeded = true;
		}

		return fullUpdateNeeded;
	}
	
	public void onProtocolProcessException(IOException e) {
		byte[] bs = new byte[2];
		bs[0] = (byte)250;
		bs[1] = 1;
		writeToClientStream(bs);
	}
	
	public Socket createConnection(String host, int port) throws IOException {
		Socket sock = new Socket();
		sock.setSoTimeout(ConsoleProxy.readTimeoutSeconds*1000);
		sock.setKeepAlive(true);
		sock.connect(new InetSocketAddress(host, port), 30000);
		return sock;
	}
	
	public void writeInit(OutputStream os) throws IOException {
	    if (options.shareDesktop) {
	        os.write(1);
	    } else {
	    	os.write(0);
	    }
	}
	
	public void swapMouseButton(Integer[] masks) {
	    if (options.reverseMouseButtons2And3) {
	    	Integer temp = masks[1];
	    	masks[1] = masks[0];
	    	masks[0] = temp;
	      }
	}
	
	public boolean onTileChange(Rectangle rowMergedRect, int row, int col) {
		// currently we don't do scan-based client update
		return true;
	}
	
	public void onRegionChange(List<Region> regionList) {
		// obsolute
	}
	
	private void signalTileDirtyEvent() {
		synchronized(tileDirtyEvent) {
			dirtyFlag = true;
			tileDirtyEvent.notifyAll();
		}
	}
	
	public String getTag() {
		return tag;
	}
	
	public void setTag(String tag) {
		this.tag = tag;
	}
	
	//
	// AJAX Image manipulation 
	//
	public void copyTile(Graphics2D g, int x, int y, Rectangle rc) {
		if(vc != null && vc.memImage != null) {
			synchronized(vc.memImage) {
				g.drawImage(vc.memImage, x, y, x + rc.width, y + rc.height, 
					rc.x, rc.y, rc.x + rc.width, rc.y + rc.height, null);
			}
		}
	}
	
	public byte[] getFrameBufferJpeg() {
		int width = 800;
		int height = 600;
		if(vc != null) {
			width = vc.scaledWidth;
			height = vc.scaledHeight;
		}
		
		if(s_logger.isTraceEnabled())
			s_logger.trace("getFrameBufferJpeg, w: " + width + ", h: " + height);
		
		BufferedImage bufferedImage = new BufferedImage(width, height,
				BufferedImage.TYPE_3BYTE_BGR);
		if(vc != null && vc.memImage != null) {
			synchronized(vc.memImage) {
				Graphics2D g = bufferedImage.createGraphics();
				g.drawImage(vc.memImage, 0, 0, width, height, 0, 0, width, height, null);
			}
		}
		
		byte[] imgBits = null;
		try {
			imgBits = jpegFromImage(bufferedImage);
		} catch (IOException e) {
		}
		return imgBits;
	}
	
	public byte[] getTilesMergedJpeg(List<TileInfo> tileList, int tileWidth, int tileHeight) {
		
		int width = Math.max(tileWidth, tileWidth*tileList.size());
		BufferedImage bufferedImage = new BufferedImage(width, tileHeight,
			BufferedImage.TYPE_3BYTE_BGR);
		
		if(s_logger.isTraceEnabled())
			s_logger.trace("Create merged image, w: " + width + ", h: " + tileHeight);
		
		if(vc != null && vc.memImage != null) {
			synchronized(vc.memImage) {
				Graphics2D g = bufferedImage.createGraphics();
				int i = 0;
				for(TileInfo tile : tileList) {
					Rectangle rc = tile.getTileRect();
					
					if(s_logger.isTraceEnabled())
						s_logger.trace("Merge tile into jpeg from (" + rc.x + "," + rc.y + "," + (rc.x + rc.width) + "," + (rc.y + rc.height) + ") to (" + i*tileWidth + ",0)" );
					
					g.drawImage(vc.memImage, i*tileWidth, 0, i*tileWidth + rc.width, rc.height, 
						rc.x, rc.y, rc.x + rc.width, rc.y + rc.height, null);
					
					i++;
				}
			}
		}
		
		byte[] imgBits = null;
		try {
			imgBits = jpegFromImage(bufferedImage);
			
			if(s_logger.isTraceEnabled())
				s_logger.trace("Merge jpeg image size: " + imgBits.length + ", tiles: " + tileList.size());
		} catch (IOException e) {
		}
		return imgBits;
	}
	
	public byte[] jpegFromImage(BufferedImage image) throws IOException {
		ByteArrayOutputStream bos = new ByteArrayOutputStream(128000);
		javax.imageio.ImageIO.write(image, "jpg", bos);
		
		byte[] jpegBits = bos.toByteArray();
		bos.close();
		return jpegBits;
	}
	
	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("/ajaximg?host=");
		sb.append(host).append("&port=").append(port).append("&sid=").append(passwordParam);
		sb.append("&key=").append(key).append("&ts=").append(System.currentTimeMillis());
		return sb.toString(); 
	}
	
	private String prepareAjaxSession(boolean init) {
		StringBuffer sb = new StringBuffer();
		
		if(init)
			ajaxSessionId++;
		
		sb.append("/ajax?host=").append(host).append("&port=").append(port);
		sb.append("&sid=").append(passwordParam).append("&sess=").append(ajaxSessionId);
		return sb.toString();
	}

	public String onAjaxClientKickoff() {
		return "onKickoff();";
	}
	
	private boolean waitForViewerReady() {
		long startTick = System.currentTimeMillis();
		while(System.currentTimeMillis() - startTick < 5000) {
			if(this.status == ConsoleProxyViewer.STATUS_NORMAL_OPERATION)
				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>";
	}
	
	public String onAjaxClientStart(String title) {
		if(!waitForViewerReady())
			return onAjaxClientConnectFailed();

		// make sure we switch to AJAX view on start
		setAjaxViewer(true);
			
		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);
		
		synchronized(this) {
			if(framebufferResized) {
				framebufferResized = false;
			}
		}
		
		int retry = 0;
		if(justCreated()) {
			tracker.initCoverageTest();
			
			try {
				rfb.writeFramebufferUpdateRequest(0, 0, tracker.getTrackWidth(), tracker.getTrackHeight(), false);
			
				while(!tracker.hasFullCoverage() && retry < 10) {
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
					}
					retry++;
				}
			} catch (IOException e1) {
				s_logger.warn("Connection was broken ");
			}
		}
		
		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++;
		}

/*		
		SimpleHash model = new SimpleHash();
		model.put("tileSequence", sbTileSequence.toString());
		model.put("imgUrl", imgUrl);
		model.put("updateUrl", updateUrl);
		model.put("width", String.valueOf(width));
		model.put("height", String.valueOf(height));
		model.put("tileWidth", String.valueOf(tileWidth));
		model.put("tileHeight", String.valueOf(tileHeight));
		model.put("title", title);
		model.put("rawKeyboard", ConsoleProxy.keyboardType == ConsoleProxy.KEYBOARD_RAW ? "true" : "false");
		
		StringWriter writer = new StringWriter();
		try {
			ConsoleProxy.processTemplate("viewer.ftl", model, writer);
		} catch (IOException e) {
			s_logger.warn("Unexpected exception in processing template.", e);
		} catch (TemplateException e) {
			s_logger.warn("Unexpected exception in processing template.", e);
		}
		StringBuffer sb = writer.getBuffer();
		if(s_logger.isTraceEnabled())
			s_logger.trace("onAjaxClientStart response: " + sb.toString());
		return sb.toString();
	*/
		return getAjaxViewerPageContent(sbTileSequence.toString(), imgUrl, 
				updateUrl, width, height, tileWidth, tileHeight, title, 
				ConsoleProxy.keyboardType == ConsoleProxy.KEYBOARD_RAW);
	}
	
	private String getAjaxViewerPageContent(String tileSequence, String imgUrl, String updateUrl, int width,
		int height, int tileWidth, int tileHeight, String title, boolean rawKeyboard) {
		
		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=\"#\" onclick=\"javascript:sendCtrlAltDel();\">", 
						"<span><img align=\"left\" src=\"/resource/images/cad.gif\" alt=\"Ctrl-Alt-Del\" />Ctrl-Alt-Del</span>", 
					"</a>", 
				"</li>",
				"<li>", 
					"<a href=\"#\" onclick=\"javascript:sendCtrlEsc();\">", 
						"<span><img align=\"left\" src=\"/resource/images/winlog.png\" alt=\"Ctrl-Esc\" style=\"width:16px;height:16px\"/>Ctrl-Esc</span>",
					"</a>", 
				"</li>",
			"</ul>",
			"<span id=\"light\" class=\"dark\"></span>", 
			"</div>",
			"<div id=\"main_panel\" tabindex=\"1\"></div>",
			"<script language=\"javascript\">",
			
			"var tileMap = [ " + tileSequence + " ];",
			"var ajaxViewer = new AjaxViewer('main_panel', '" + imgUrl + "', '" + updateUrl + "', tileMap, ", 
				String.valueOf(width) + ", " + String.valueOf(height) + ", " + String.valueOf(tileWidth) + ", " + String.valueOf(tileHeight) + ", " + (rawKeyboard ? "true" : "false") + ");",

			"$(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();";
	}
	
	public String onAjaxClientUpdate() {
		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++;
		}

/*		
		SimpleHash model = new SimpleHash();
		model.put("tileSequence", sbTileSequence.toString());
		model.put("resized", doResize);
		model.put("imgUrl", imgUrl);
		model.put("width", String.valueOf(resizedFramebufferWidth));
		model.put("height", String.valueOf(resizedFramebufferHeight));
		model.put("tileWidth", String.valueOf(tracker.getTileWidth()));
		model.put("tileHeight", String.valueOf(tracker.getTileHeight()));
		
		StringWriter writer = new StringWriter();
		try {
			ConsoleProxy.processTemplate("viewer-update.ftl", model, writer);
		} catch (IOException e) {
			s_logger.warn("Unexpected exception in processing template.", e);
		} catch (TemplateException e) {
			s_logger.warn("Unexpected exception in processing template.", e);
		}
		StringBuffer sb = writer.getBuffer();
		
		if(s_logger.isTraceEnabled())
			s_logger.trace("onAjaxClientUpdate response: " + sb.toString());
		
		return sb.toString();
*/
		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();
	}
	
	
	public long getAjaxSessionId() {
		return this.ajaxSessionId;
	}
	
	public AjaxFIFOImageCache getAjaxImageCache() {
		return ajaxImageCache;
	}
	
	public boolean isAjaxViewer() {
		return ajaxViewer;
	}

	public synchronized void setAjaxViewer(boolean ajaxViewer) {
		if(this.ajaxViewer != ajaxViewer) {
			if(this.ajaxViewer) {
				// previous session was AJAX session
				this.ajaxSessionId++;		// increase the session id so that it will disconnect existing AJAX viewer
			} else {
				// close java client session
				if(clientStream != null) {
					byte[] bs = new byte[2];
					bs[0] = (byte)250;
					bs[1] = 1;
					writeToClientStream(bs);
					
					try {
						clientStream.close();
					} catch (IOException e) {
					}
					clientStream = null;
				}
			}
			this.ajaxViewer = ajaxViewer;
		}
	}
	
	public void writeServer(byte[] b, int off, int len) {
		synchronized (this) {
			if (!rfb.closed()) {
				try {
					// We lock the viewer to avoid race condition when connecting one 
					// client forces the current client to disconnect.
					rfb.os.write(b, off, len);
					rfb.os.flush();
				} catch (IOException e) {
					// Swallow the exception because we want the client connection to sustain
					// even when server connection is severed and reestablished.
					s_logger.info("Ignore exception when writing to server: " + e);
					rfb.close();
				}
			} else {
				s_logger.info("Dropping client event because server connection is closed ");
			}
		}
	}
	
	public void sendClientMouseEvent(int event, int x, int y, int code, int modifiers) {
		if(code == 2)
			modifiers |= MouseEvent.BUTTON3_MASK;
		else
			modifiers |= MouseEvent.BUTTON1_MASK;

		int id = 0; 
		if(event == 1)
			id = MouseEvent.MOUSE_MOVED;
		else if(event == 2)
			id = MouseEvent.MOUSE_PRESSED;
		else if(event == 3)
			id = MouseEvent.MOUSE_RELEASED;
		else if(event == 8)
			id = MouseEvent.MOUSE_PRESSED;

		long curTicks = System.currentTimeMillis();
		MouseEvent mouseEvent = new MouseEvent(vc, id,
			curTicks, modifiers, x, y, 1, false);
		
		synchronized (this) {
			if (rfb != null && !rfb.closed()) {
				try {
					rfb.writePointerEvent(mouseEvent);
					if(event == 8) {
						if(s_logger.isTraceEnabled())
							s_logger.trace("Replay mouse double click event at " + x + "," + y);

						mouseEvent = new MouseEvent(vc, MouseEvent.MOUSE_RELEASED,
								curTicks, modifiers, x, y, 1, false);
						rfb.writePointerEvent(mouseEvent);
						
						mouseEvent = new MouseEvent(vc, MouseEvent.MOUSE_PRESSED,
								curTicks, modifiers, x, y, 1, false);
						rfb.writePointerEvent(mouseEvent);
						
						mouseEvent = new MouseEvent(vc, MouseEvent.MOUSE_RELEASED,
								curTicks, modifiers, x, y, 1, false);
						rfb.writePointerEvent(mouseEvent);
					}
				} catch (IOException e) {
					s_logger.warn("Exception while sending mouse event. ", e);
				}
			}
		}
	}

	public void sendClientRawKeyboardEvent(int event, int code, int modifiers) {
		code = ConsoleProxyAjaxKeyMapper.getInstance().getJvmKeyCode(code);
		switch(event) {
		case 4 : 	// Key press
			//
			// special handling for ' and " (keycode: 222, char code : 39 and 34
			//
			if(code == 39 || code == 34) {
				writeKeyboardEvent(KeyEvent.KEY_PRESSED, 222, (char)code, getAwtModifiers(modifiers));
			}
			break;

		case 5 :	// Key down
			if((modifiers & ConsoleProxyViewer.CTRL_KEY_MASK) != 0 && (modifiers & ConsoleProxyViewer.ALT_KEY_MASK) != 0 && code == KeyEvent.VK_INSERT) {
				code = KeyEvent.VK_DELETE;
			}
			
			if(code != 222) {
				writeKeyboardEvent(KeyEvent.KEY_PRESSED, code, 
					ConsoleProxyAjaxKeyMapper.getInstance().shiftedKeyCharFromKeyCode(code, (modifiers & ConsoleProxyViewer.SHIFT_KEY_MASK) != 0), 
					getAwtModifiers(modifiers));
			}
			break;
			
		case 6 :	// Key Up
			writeKeyboardEvent(KeyEvent.KEY_RELEASED, code, 
				ConsoleProxyAjaxKeyMapper.getInstance().shiftedKeyCharFromKeyCode(code, (modifiers & ConsoleProxyViewer.SHIFT_KEY_MASK) != 0), 
				getAwtModifiers(modifiers));
			break;
		}
	}

	public void sendClientKeyboardEvent(int event, int code, int modifiers) {
		int vkCode;
		switch(event) {
		case 4 : 	// Key press
			if(code == 0 || (modifiers & (ConsoleProxyViewer.CTRL_KEY_MASK | ConsoleProxyViewer.META_KEY_MASK | ConsoleProxyViewer.ALT_KEY_MASK)) != 0) {
				// if code is extend keys or has ctrl, alt, meta being pressed, ignore javascript key-press event
				return;
			}
			
			vkCode = ConsoleProxyAjaxKeyMapper.getInstance().getRegularCharVkCode(code);
			if(vkCode > 0) {
				writeKeyboardEvent(KeyEvent.KEY_PRESSED, vkCode, (char)code, 0); 
				writeKeyboardEvent(KeyEvent.KEY_RELEASED, vkCode, (char)code, 0);
			}
			break;

		case 5 :	// Key down
			vkCode = ConsoleProxyAjaxKeyMapper.getInstance().getActionCharVkCode(code);
			if(vkCode >= 0 || (modifiers & (ConsoleProxyViewer.CTRL_KEY_MASK | ConsoleProxyViewer.META_KEY_MASK | ConsoleProxyViewer.ALT_KEY_MASK)) != 0) {
				if(vkCode < 0) {
					vkCode = ConsoleProxyAjaxKeyMapper.getInstance().getRegularCharVkCode(code);
					
					if((modifiers & ConsoleProxyViewer.CTRL_KEY_MASK) != 0) {  	// if control-key is pressed, always use lower-case char-code
						if(vkCode >= (int)'A' && vkCode <= (int)'Z')
							vkCode = (int)'a' + (vkCode - (int)'A');
					}
				}
				
				if((modifiers & ConsoleProxyViewer.CTRL_KEY_MASK) != 0 && (modifiers & ConsoleProxyViewer.ALT_KEY_MASK) != 0 && vkCode == KeyEvent.VK_INSERT) {
					vkCode = KeyEvent.VK_DELETE;
				}
				
				writeKeyboardEvent(KeyEvent.KEY_PRESSED, vkCode, (char)vkCode,
					getAwtModifiers(modifiers));
			}
			break;
			
		case 6 :	// Key Up
			vkCode = ConsoleProxyAjaxKeyMapper.getInstance().getActionCharVkCode(code);
			if(vkCode >= 0 || (modifiers & (ConsoleProxyViewer.CTRL_KEY_MASK | ConsoleProxyViewer.META_KEY_MASK | ConsoleProxyViewer.ALT_KEY_MASK)) != 0) {
				if(vkCode < 0) {
					vkCode = ConsoleProxyAjaxKeyMapper.getInstance().getRegularCharVkCode(code);

					if((modifiers & ConsoleProxyViewer.CTRL_KEY_MASK) != 0) {	// if control-key is pressed, always use lower-case char-code
						if(vkCode >= (int)'A' && vkCode <= (int)'Z')
							vkCode = (int)'a' + (vkCode - (int)'A');
					}
					
					if((modifiers & ConsoleProxyViewer.CTRL_KEY_MASK) != 0 && (modifiers & ConsoleProxyViewer.ALT_KEY_MASK) != 0 && vkCode == KeyEvent.VK_INSERT) {
						vkCode = KeyEvent.VK_DELETE;
					}
				}

				writeKeyboardEvent(KeyEvent.KEY_RELEASED, vkCode, (char)vkCode,
					getAwtModifiers(modifiers));
			}
			break;
		}
	}
	
	private static int getAwtModifiers(int jsModifiers) {
		int awtModifiers = 0;
		
		if((jsModifiers & ConsoleProxyViewer.SHIFT_KEY_MASK) != 0) {
			awtModifiers |= InputEvent.SHIFT_DOWN_MASK;
		}
		
		if((jsModifiers & ConsoleProxyViewer.CTRL_KEY_MASK) != 0) {
			awtModifiers |= InputEvent.CTRL_DOWN_MASK;
		}
		
		if((jsModifiers & ConsoleProxyViewer.ALT_KEY_MASK) != 0) {
			awtModifiers |= InputEvent.ALT_DOWN_MASK;
		}
		
		return awtModifiers;
	}
	
	private void writeKeyboardEvent(int keyEventType, int code, char keyChar, int modifiers) {
		KeyEvent keyEvent;
		try {
			keyEvent = new KeyEvent(vc, keyEventType, 
				System.currentTimeMillis(), modifiers, code, keyChar);
		} catch(Exception e) {
			s_logger.warn("Unable to construct KeyEvent object, key code: " + code + ", keyChar: " + keyChar + " ", e);
			return;
		}
		
		synchronized (this) {
			if (rfb != null && !rfb.closed()) {
				try {
					rfb.writeKeyEvent(keyEvent);
				} catch (IOException e) {
					s_logger.warn("Exception while sending keyboard event. ", e);
				}
			}
		}
	}
}
