// 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.io.IOException;
import java.net.URI;
import java.net.UnknownHostException;

import org.apache.log4j.Logger;

import com.cloud.consoleproxy.vnc.FrameBufferCanvas;
import com.cloud.consoleproxy.vnc.RfbConstants;
import com.cloud.consoleproxy.vnc.VncClient;

/**
 * 
 * @author Kelven Yang
 * ConsoleProxyVncClient bridges a VNC engine with the front-end AJAX viewer
 * 
 */
public class ConsoleProxyVncClient extends ConsoleProxyClientBase {
	private static final Logger s_logger = Logger.getLogger(ConsoleProxyVncClient.class);

	private static final int SHIFT_KEY_MASK = 64;
	private static final int CTRL_KEY_MASK = 128;
	private static final int META_KEY_MASK = 256;
	private static final int ALT_KEY_MASK = 512;
	
	private static final int X11_KEY_SHIFT = 0xffe1;
	private static final int X11_KEY_CTRL = 0xffe3;
	private static final int X11_KEY_ALT = 0xffe9;
	private static final int X11_KEY_META = 0xffe7;
	
	private VncClient client;
	private Thread worker;
	private boolean workerDone = false;
	
	private int lastModifierStates = 0;
	private int lastPointerMask = 0;
	
	public ConsoleProxyVncClient() {
	}
	
	public boolean isHostConnected() {
		if(client != null)
			return client.isHostConnected();
		
		return false;
	}
	
	@Override
	public boolean isFrontEndAlive() {
		if(workerDone || System.currentTimeMillis() - getClientLastFrontEndActivityTime() > ConsoleProxy.VIEWER_LINGER_SECONDS*1000) {
			s_logger.info("Front end has been idle for too long");
			return false;
		}
		return true;
	}

	@Override
	public void initClient(ConsoleProxyClientParam param) {
		setClientParam(param);
		
		client = new VncClient(this);
		worker = new Thread(new Runnable() {
			public void run() {
				String tunnelUrl = getClientParam().getClientTunnelUrl();
				String tunnelSession = getClientParam().getClientTunnelSession();
				
				for(int i = 0; i < 15; i++) {
					try {
						if(tunnelUrl != null && !tunnelUrl.isEmpty() && tunnelSession != null && !tunnelSession.isEmpty()) {
							URI uri = new URI(tunnelUrl);
							s_logger.info("Connect to VNC server via tunnel. url: " + tunnelUrl + ", session: " + tunnelSession);
							
							ConsoleProxy.ensureRoute(uri.getHost());
							client.connectTo(
								uri.getHost(), uri.getPort(), 
								uri.getPath() + "?" + uri.getQuery(), 
								tunnelSession, "https".equalsIgnoreCase(uri.getScheme()),
								getClientHostPassword());
						} else {
							s_logger.info("Connect to VNC server directly. host: " + getClientHostAddress() + ", port: " + getClientHostPort());
							ConsoleProxy.ensureRoute(getClientHostAddress());
							client.connectTo(getClientHostAddress(), getClientHostPort(), getClientHostPassword());
						}
					} catch (UnknownHostException e) {
						s_logger.error("Unexpected exception (will retry until timeout)", e);
					} catch (IOException e) {
						s_logger.error("Unexpected exception (will retry until timeout) ", e);
					} catch (Throwable e) {
						s_logger.error("Unexpected exception (will retry until timeout) ", e);
					}
					
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
					}

					if(tunnelUrl != null && !tunnelUrl.isEmpty() && tunnelSession != null && !tunnelSession.isEmpty()) {
						ConsoleProxyAuthenticationResult authResult = ConsoleProxy.reAuthenticationExternally(getClientParam());
						if(authResult != null && authResult.isSuccess()) {
							if(authResult.getTunnelUrl() != null && !authResult.getTunnelUrl().isEmpty() && 
								authResult.getTunnelSession() != null && !authResult.getTunnelSession().isEmpty()) {
								tunnelUrl = authResult.getTunnelUrl();
								tunnelSession = authResult.getTunnelSession();
								
								s_logger.info("Reset XAPI session. url: " + tunnelUrl + ", session: " + tunnelSession);
							}
						}
					}
				}

				s_logger.info("Receiver thread stopped.");
				workerDone = true;
			    client.getClientListener().onClientClose();
			}
		});
		
		worker.setDaemon(true);
		worker.start();
	}
	
	@Override
	public void closeClient() {
		if(client != null)
			client.shutdown();
	}
	
	@Override
	public void onClientConnected() {
	}
	
	public void onClientClose() {
		s_logger.info("Received client close indication. remove viewer from map.");
		
		ConsoleProxy.removeViewer(this);
	}
	
	@Override
	public void onFramebufferUpdate(int x, int y, int w, int h) {
		super.onFramebufferUpdate(x, y, w, h);
		client.requestUpdate(false);
	}

	public void sendClientRawKeyboardEvent(InputEventType event, int code, int modifiers) {
		if(client == null)
			return;
		
		updateFrontEndActivityTime();
		
		switch(event) {
		case KEY_DOWN :
			sendModifierEvents(modifiers);
			client.sendClientKeyboardEvent(RfbConstants.KEY_DOWN, code, 0);
			break;
			
		case KEY_UP :
			client.sendClientKeyboardEvent(RfbConstants.KEY_UP, code, 0);
			sendModifierEvents(0);
			break;
			
		case KEY_PRESS :
			break;
			
		default :
			assert(false);
			break;
		}
	}
	
	public void sendClientMouseEvent(InputEventType event, int x, int y, int code, int modifiers) {
		if(client == null)
			return;
		
		updateFrontEndActivityTime();

	    if (event == InputEventType.MOUSE_DOWN) {
	    	if (code == 2) {
	    		lastPointerMask |= 4;
	    	} else if (code == 0) {
	    		lastPointerMask |= 1;
	    	}
	    }
	    
	    if (event == InputEventType.MOUSE_UP) {
	    	if (code == 2) {
	    		lastPointerMask ^= 4;
	    	} else if (code == 0) {
	    		lastPointerMask ^= 1;
	    	}
	    }
	    	
		sendModifierEvents(modifiers);
		client.sendClientMouseEvent(lastPointerMask, x, y, code, modifiers);
		if(lastPointerMask == 0)
			sendModifierEvents(0);
	}
	
	@Override
	protected FrameBufferCanvas getFrameBufferCavas() {
		if(client != null)
			return client.getFrameBufferCanvas();
		return null;
	}
	
	private void sendModifierEvents(int modifiers) {
		if((modifiers & SHIFT_KEY_MASK) != (lastModifierStates & SHIFT_KEY_MASK))
			client.sendClientKeyboardEvent((modifiers & SHIFT_KEY_MASK) != 0 ? RfbConstants.KEY_DOWN : RfbConstants.KEY_UP, X11_KEY_SHIFT, 0);
			
		if((modifiers & CTRL_KEY_MASK) != (lastModifierStates & CTRL_KEY_MASK))
			client.sendClientKeyboardEvent((modifiers & CTRL_KEY_MASK) != 0 ? RfbConstants.KEY_DOWN : RfbConstants.KEY_UP, X11_KEY_CTRL, 0);

		if((modifiers & META_KEY_MASK) != (lastModifierStates & META_KEY_MASK))
			client.sendClientKeyboardEvent((modifiers & META_KEY_MASK) != 0 ? RfbConstants.KEY_DOWN : RfbConstants.KEY_UP, X11_KEY_META, 0);
		
		if((modifiers & ALT_KEY_MASK) != (lastModifierStates & ALT_KEY_MASK))
			client.sendClientKeyboardEvent((modifiers & ALT_KEY_MASK) != 0 ? RfbConstants.KEY_DOWN : RfbConstants.KEY_UP, X11_KEY_ALT, 0);
		
		lastModifierStates = modifiers;
	}
}
