// Copyright 2012 Citrix Systems, Inc. Licensed under the
// Apache License, Version 2.0 (the "License"); you may not use this
// file except in compliance with the License.  Citrix Systems, Inc.
// reserves all rights not expressly granted by 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.
// 
// Automatically generated by addcopyright.py at 04/03/2012
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;

/**
 * 
 * @author Kelven Yang
 * 
 * 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);
	}
}
