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