// 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.vnc;

import java.awt.Frame;
import java.awt.ScrollPane;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.spec.KeySpec;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

import com.cloud.consoleproxy.ConsoleProxyClientListener;
import com.cloud.consoleproxy.util.Logger;
import com.cloud.consoleproxy.util.RawHTTP;
import com.cloud.consoleproxy.vnc.packet.client.KeyboardEventPacket;
import com.cloud.consoleproxy.vnc.packet.client.MouseEventPacket;

public class VncClient {
  private static final Logger s_logger = Logger.getLogger(VncClient.class);

  private Socket socket;
  private DataInputStream is;
  private DataOutputStream os;

  private VncScreenDescription screen = new VncScreenDescription();

  private VncClientPacketSender sender;
  private VncServerPacketReceiver receiver;
  
  private boolean noUI = false;
  private ConsoleProxyClientListener clientListener = null;

  public static void main(String args[]) {
    if (args.length < 3) {
      printHelpMessage();
      System.exit(1);
    }

    String host = args[0];
    String port = args[1];
    String password = args[2];

    try {
      new VncClient(host, Integer.parseInt(port), password, false, null);
    } catch (NumberFormatException e) {
      s_logger.error("Incorrect VNC server port number: " + port + ".");
      System.exit(1);
    } catch (UnknownHostException e) {
    	s_logger.error("Incorrect VNC server host name: " + host + ".");
      System.exit(1);
    } catch (IOException e) {
    	s_logger.error("Cannot communicate with VNC server: " + e.getMessage());
      System.exit(1);
    } catch (Throwable e) {
    	s_logger.error("An error happened: " + e.getMessage());
    	System.exit(1);
    }
    System.exit(0);
  }

  private static void printHelpMessage() {
    /* LOG */s_logger.info("Usage: HOST PORT PASSWORD.");
  }
  
  public VncClient(ConsoleProxyClientListener clientListener) {
	this.noUI = true;
	this.clientListener = clientListener;
  }

  public VncClient(String host, int port, String password, boolean noUI, ConsoleProxyClientListener clientListener) 
  	throws UnknownHostException, IOException {
	  
    this.noUI = noUI;
    this.clientListener = clientListener;
    connectTo(host, port, password);
  }

  public void shutdown() {
	if(sender != null)
		sender.closeConnection();
	
	if(receiver != null)
		receiver.closeConnection();

	if(is != null) {
	  try {
	    is.close();
	  } catch (Throwable e) {
	  }
	}

	if(os != null) {
	  try {
	    os.close();
	  } catch (Throwable e) {
	  }
	}
	
	if(socket != null) {
	  try {
	    socket.close();
	  } catch (Throwable e) {
	  }
	}
  }

  public ConsoleProxyClientListener getClientListener() {
	  return clientListener; 
  }
  
  public void connectTo(String host, int port, String path,
    String session, boolean useSSL, String sid) throws UnknownHostException, IOException {
	if(port < 0) {
		if(useSSL)
			port = 443;
		else
			port = 80;
	}
		
	RawHTTP tunnel = new RawHTTP("CONNECT", host, port, path, session, useSSL);
	this.socket = tunnel.connect();
	doConnect(sid);
  }
  
  public void connectTo(String host, int port, String password) throws UnknownHostException, IOException {
    // Connect to server
	s_logger.info("Connecting to VNC server " + host + ":" + port + "...");
    this.socket = new Socket(host, port);
    doConnect(password);
  }
  
  private void doConnect(String password) throws IOException {
    is = new DataInputStream(socket.getInputStream());
    os = new DataOutputStream(socket.getOutputStream());

    // Initialize connection
    handshake();
    authenticate(password);
    initialize();
    
	s_logger.info("Connecting to VNC server succeeded, start session");

    // Run client-to-server packet sender
    sender = new VncClientPacketSender(os, screen, this);

    // Create buffered image canvas
    BufferedImageCanvas canvas = new BufferedImageCanvas(sender, screen.getFramebufferWidth(), screen.getFramebufferHeight());

    // Subscribe packet sender to various events
    canvas.addMouseListener(sender);
    canvas.addMouseMotionListener(sender);
    canvas.addKeyListener(sender);

    Frame frame = null;
    if(!noUI)
    	frame = createVncClientMainWindow(canvas, screen.getDesktopName());

    new Thread(sender).start();

    // Run server-to-client packet receiver
    receiver = new VncServerPacketReceiver(is, canvas, screen, this, sender, clientListener);
    try {
      receiver.run();
    } finally {
      if(frame != null) {
	    frame.setVisible(false);
	    frame.dispose();
      }
      this.shutdown();
    }
  }

  private Frame createVncClientMainWindow(BufferedImageCanvas canvas, String title) {
    // Create AWT windows
    final Frame frame = new Frame(title + " - VNCle");

    // Use scrolling pane to support screens, which are larger than ours
    ScrollPane scroller = new ScrollPane(ScrollPane.SCROLLBARS_AS_NEEDED);
    scroller.add(canvas);
    scroller.setSize(screen.getFramebufferWidth(), screen.getFramebufferHeight());

    frame.add(scroller);
    frame.pack();
    frame.setVisible(true);

    frame.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent evt) {
        frame.setVisible(false);
        shutdown();
      }
    });

    return frame;
  }

  /**
   * Handshake with VNC server.
   */
  private void handshake() throws IOException {

    // Read protocol version
    byte[] buf = new byte[12];
    is.readFully(buf);
    String rfbProtocol = new String(buf);

    // Server should use RFB protocol 3.x
    if (!rfbProtocol.contains(RfbConstants.RFB_PROTOCOL_VERSION_MAJOR)) {
      s_logger.error("Cannot handshake with VNC server. Unsupported protocol version: \"" + rfbProtocol + "\".");
      throw new RuntimeException("Cannot handshake with VNC server. Unsupported protocol version: \"" + rfbProtocol + "\".");
    }

    // Send response: we support RFB 3.3 only
    String ourProtocolString = RfbConstants.RFB_PROTOCOL_VERSION + "\n";
    os.write(ourProtocolString.getBytes());
    os.flush();
  }

  /**
   * VNC authentication.
   */
  private void authenticate(String password) throws IOException {
    // Read security type
    int authType = is.readInt();

    switch (authType) {
    case RfbConstants.CONNECTION_FAILED: {
      // Server forbids to connect. Read reason and throw exception

      int length = is.readInt();
      byte[] buf = new byte[length];
      is.readFully(buf);
      String reason = new String(buf, RfbConstants.CHARSET);
      
      s_logger.error("Authentication to VNC server is failed. Reason: " + reason);
      throw new RuntimeException("Authentication to VNC server is failed. Reason: " + reason);
    }

    case RfbConstants.NO_AUTH: {
      // Client can connect without authorization. Nothing to do.
      break;
    }

    case RfbConstants.VNC_AUTH: {
      s_logger.info("VNC server requires password authentication");
      doVncAuth(password);
      break;
    }

    default:
      s_logger.error("Unsupported VNC protocol authorization scheme, scheme code: " + authType + ".");
      throw new RuntimeException("Unsupported VNC protocol authorization scheme, scheme code: " + authType + ".");
    }
  }

  /**
   * Encode client password and send it to server.
   */
  private void doVncAuth(String password) throws IOException {

    // Read challenge
    byte[] challenge = new byte[16];
    is.readFully(challenge);

    // Encode challenge with password
    byte[] response;
    try {
      response = encodePassword(challenge, password);
    } catch (Exception e) {
      s_logger.error("Cannot encrypt client password to send to server: " + e.getMessage());
      throw new RuntimeException("Cannot encrypt client password to send to server: " + e.getMessage());
    }

    // Send encoded challenge
    os.write(response);
    os.flush();

    // Read security result
    int authResult = is.readInt();

    switch (authResult) {
    case RfbConstants.VNC_AUTH_OK: {
      // Nothing to do
      break;
    }

    case RfbConstants.VNC_AUTH_TOO_MANY:
      s_logger.error("Connection to VNC server failed: too many wrong attempts.");
      throw new RuntimeException("Connection to VNC server failed: too many wrong attempts.");

    case RfbConstants.VNC_AUTH_FAILED:
        s_logger.error("Connection to VNC server failed: wrong password.");
      throw new RuntimeException("Connection to VNC server failed: wrong password.");

    default:
      s_logger.error("Connection to VNC server failed, reason code: " + authResult);
      throw new RuntimeException("Connection to VNC server failed, reason code: " + authResult);
    }
  }

  /**
   * Encode password using DES encryption with given challenge.
   * 
   * @param challenge
   *          a random set of bytes.
   * @param password
   *          a password
   * @return DES hash of password and challenge
   */
  public byte[] encodePassword(byte[] challenge, String password) throws Exception {
    // VNC password consist of up to eight ASCII characters.
    byte[] key = { 0, 0, 0, 0, 0, 0, 0, 0 }; // Padding
    byte[] passwordAsciiBytes = password.getBytes(RfbConstants.CHARSET);
    System.arraycopy(passwordAsciiBytes, 0, key, 0, Math.min(password.length(), 8));

    // Flip bytes (reverse bits) in key
    for (int i = 0; i < key.length; i++) {
      key[i] = flipByte(key[i]);
    }

    KeySpec desKeySpec = new DESKeySpec(key);
    SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DES");
    SecretKey secretKey = secretKeyFactory.generateSecret(desKeySpec);
    Cipher cipher = Cipher.getInstance("DES/ECB/NoPadding");
    cipher.init(Cipher.ENCRYPT_MODE, secretKey);

    byte[] response = cipher.doFinal(challenge);
    return response;
  }

  /**
   * Reverse bits in byte, so least significant bit will be most significant
   * bit. E.g. 01001100 will become 00110010.
   * 
   * See also: http://www.vidarholen.net/contents/junk/vnc.html ,
   * http://bytecrafter .blogspot.com/2010/09/des-encryption-as-used-in-vnc.html
   * 
   * @param b
   *          a byte
   * @return byte in reverse order
   */
  private static byte flipByte(byte b) {
    int b1_8 = (b & 0x1) << 7;
    int b2_7 = (b & 0x2) << 5;
    int b3_6 = (b & 0x4) << 3;
    int b4_5 = (b & 0x8) << 1;
    int b5_4 = (b & 0x10) >>> 1;
    int b6_3 = (b & 0x20) >>> 3;
    int b7_2 = (b & 0x40) >>> 5;
    int b8_1 = (b & 0x80) >>> 7;
    byte c = (byte) (b1_8 | b2_7 | b3_6 | b4_5 | b5_4 | b6_3 | b7_2 | b8_1);
    return c;
  }

  private void initialize() throws IOException {
    // Send client initialization message
    {
      // Send shared flag
      os.writeByte(RfbConstants.EXCLUSIVE_ACCESS);
      os.flush();
    }

    // Read server initialization message
    {
      // Read frame buffer size
      int framebufferWidth = is.readUnsignedShort();
      int framebufferHeight = is.readUnsignedShort();
      screen.setFramebufferSize(framebufferWidth, framebufferHeight);
      if(clientListener != null)
    	  clientListener.onFramebufferSizeChange(framebufferWidth, framebufferHeight);
    }

    // Read pixel format
    {
      int bitsPerPixel = is.readUnsignedByte();
      int depth = is.readUnsignedByte();

      int bigEndianFlag = is.readUnsignedByte();
      int trueColorFlag = is.readUnsignedByte();

      int redMax = is.readUnsignedShort();
      int greenMax = is.readUnsignedShort();
      int blueMax = is.readUnsignedShort();

      int redShift = is.readUnsignedByte();
      int greenShift = is.readUnsignedByte();
      int blueShift = is.readUnsignedByte();

      // Skip padding
      is.skipBytes(3);

      screen.setPixelFormat(bitsPerPixel, depth, bigEndianFlag, trueColorFlag, redMax, greenMax, blueMax, redShift, greenShift, blueShift);
    }

    // Read desktop name
    {
      int length = is.readInt();
      byte buf[] = new byte[length];
      is.readFully(buf);
      String desktopName = new String(buf, RfbConstants.CHARSET);
      screen.setDesktopName(desktopName);
    }
  }
  
  public FrameBufferCanvas getFrameBufferCanvas() {
    if(receiver != null)
      return receiver.getCanvas();
	  
	return null;
  }
  
  public void requestUpdate(boolean fullUpdate) {
	if(fullUpdate)
		sender.requestFullScreenUpdate();
	else
		sender.imagePaintedOnScreen();  
  }
  
  public void sendClientKeyboardEvent(int event, int code, int modifiers) {
    sender.sendClientPacket(new KeyboardEventPacket(event, code));
  }
  
  public void sendClientMouseEvent(int event, int x, int y, int code, int modifiers) {
    sender.sendClientPacket(new MouseEventPacket(event, x, y));
  }
  
  public boolean isHostConnected() {
	  return receiver != null && receiver.isConnectionAlive();
  }
}
