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

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.io.DataOutputStream;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;

import com.cloud.consoleproxy.util.Logger;
import com.cloud.consoleproxy.vnc.packet.client.ClientPacket;
import com.cloud.consoleproxy.vnc.packet.client.FramebufferUpdateRequestPacket;
import com.cloud.consoleproxy.vnc.packet.client.KeyboardEventPacket;
import com.cloud.consoleproxy.vnc.packet.client.MouseEventPacket;
import com.cloud.consoleproxy.vnc.packet.client.SetEncodingsPacket;
import com.cloud.consoleproxy.vnc.packet.client.SetPixelFormatPacket;

public class VncClientPacketSender implements Runnable, PaintNotificationListener, KeyListener, MouseListener, MouseMotionListener, FrameBufferUpdateListener {
  private static final Logger s_logger = Logger.getLogger(VncClientPacketSender.class);

  // Queue for outgoing packets
  private final BlockingQueue<ClientPacket> queue = new ArrayBlockingQueue<ClientPacket>(30);

  private final DataOutputStream os;
  private final VncScreenDescription screen;
  private final VncClient vncConnection;

  private boolean connectionAlive = true;

  // Don't send update request again until we receive next frame buffer update
  private boolean updateRequestSent = false;

  public VncClientPacketSender(DataOutputStream os, VncScreenDescription screen, VncClient vncConnection) {
    this.os = os;
    this.screen = screen;
    this.vncConnection = vncConnection;

    sendSetPixelFormat();
    sendSetEncodings();
    requestFullScreenUpdate();
  }
  
  public void sendClientPacket(ClientPacket packet) {
	  queue.add(packet);
  }

  @Override
  public void run() {
    try {
      while (connectionAlive) {
        ClientPacket packet = queue.poll(1, TimeUnit.SECONDS);
        if (packet != null) {
          packet.write(os);
          os.flush();
        }
      }
    } catch (Throwable e) {
      s_logger.error("Unexpected exception: ", e);
      if (connectionAlive) {
        closeConnection();
        vncConnection.shutdown();
      }
    }
  }

  private void sendSetEncodings() {
    queue.add(new SetEncodingsPacket(RfbConstants.SUPPORTED_ENCODINGS_ARRAY));
  }

  private void sendSetPixelFormat() {
    if (!screen.isRGB888_32_LE()) {
      queue.add(new SetPixelFormatPacket(screen, 32, 24, RfbConstants.LITTLE_ENDIAN, RfbConstants.TRUE_COLOR, 255, 255, 255, 16, 8, 0));
    }
  }

  public void closeConnection() {
    connectionAlive = false;
  }

  public void requestFullScreenUpdate() {
    queue.add(new FramebufferUpdateRequestPacket(RfbConstants.FRAMEBUFFER_FULL_UPDATE_REQUEST, 0, 0, screen.getFramebufferWidth(), screen
        .getFramebufferHeight()));
    updateRequestSent = true;
  }

  @Override
  public void imagePaintedOnScreen() {
    if (!updateRequestSent) {
      queue.add(new FramebufferUpdateRequestPacket(RfbConstants.FRAMEBUFFER_INCREMENTAL_UPDATE_REQUEST, 0, 0, screen.getFramebufferWidth(), screen
          .getFramebufferHeight()));
      updateRequestSent = true;
    }
  }

  @Override
  public void frameBufferPacketReceived() {
    updateRequestSent = false;
  }

  @Override
  public void mouseDragged(MouseEvent e) {
    queue.add(new MouseEventPacket(mapAwtModifiersToVncButtonMask(e.getModifiersEx()), e.getX(), e.getY()));
  }

  @Override
  public void mouseMoved(MouseEvent e) {
    queue.add(new MouseEventPacket(mapAwtModifiersToVncButtonMask(e.getModifiersEx()), e.getX(), e.getY()));
  }

  @Override
  public void mouseClicked(MouseEvent e) {
    // Nothing to do
  }

  @Override
  public void mousePressed(MouseEvent e) {
    queue.add(new MouseEventPacket(mapAwtModifiersToVncButtonMask(e.getModifiersEx()), e.getX(), e.getY()));
  }

  @Override
  public void mouseReleased(MouseEvent e) {
    queue.add(new MouseEventPacket(mapAwtModifiersToVncButtonMask(e.getModifiersEx()), e.getX(), e.getY()));
  }

  @Override
  public void mouseEntered(MouseEvent e) {
    // Nothing to do
  }

  @Override
  public void mouseExited(MouseEvent e) {
    // Nothing to do
  }

  /**
   * Current state of buttons 1 to 8 are represented by bits 0 to 7 of
   * button-mask respectively, 0 meaning up, 1 meaning down (pressed). On a
   * conventional mouse, buttons 1, 2 and 3 correspond to the left, middle and
   * right buttons on the mouse. On a wheel mouse, each step of the wheel
   * upwards is represented by a press and release of button 4, and each step
   * downwards is represented by a press and release of button 5.
   * 
   * @param modifiers
   *          extended modifiers from AWT mouse event
   * @return VNC mouse button mask
   */
  public static int mapAwtModifiersToVncButtonMask(int modifiers) {
    int mask = (((modifiers & MouseEvent.BUTTON1_DOWN_MASK) != 0) ? 0x1 : 0) | (((modifiers & MouseEvent.BUTTON2_DOWN_MASK) != 0) ? 0x2 : 0)
        | (((modifiers & MouseEvent.BUTTON3_DOWN_MASK) != 0) ? 0x4 : 0);
    return mask;
  }

  @Override
  public void keyTyped(KeyEvent e) {
    // Do nothing
  }

  @Override
  public void keyPressed(KeyEvent e) {
    ClientPacket request = new KeyboardEventPacket(RfbConstants.KEY_DOWN, mapAwtKeyToVncKey(e.getKeyCode()));
    queue.add(request);
  }

  @Override
  public void keyReleased(KeyEvent e) {
    ClientPacket request = new KeyboardEventPacket(RfbConstants.KEY_UP, mapAwtKeyToVncKey(e.getKeyCode()));
    queue.add(request);
  }

  private int mapAwtKeyToVncKey(int key) {
    switch (key) {
    case KeyEvent.VK_BACK_SPACE:
      return 0xff08;
    case KeyEvent.VK_TAB:
      return 0xff09;
    case KeyEvent.VK_ENTER:
      return 0xff0d;
    case KeyEvent.VK_ESCAPE:
      return 0xff1b;
    case KeyEvent.VK_INSERT:
      return 0xff63;
    case KeyEvent.VK_DELETE:
      return 0xffff;
    case KeyEvent.VK_HOME:
      return 0xff50;
    case KeyEvent.VK_END:
      return 0xff57;
    case KeyEvent.VK_PAGE_UP:
      return 0xff55;
    case KeyEvent.VK_PAGE_DOWN:
      return 0xff56;
    case KeyEvent.VK_LEFT:
      return 0xff51;
    case KeyEvent.VK_UP:
      return 0xff52;
    case KeyEvent.VK_RIGHT:
      return 0xff53;
    case KeyEvent.VK_DOWN:
      return 0xff54;
    case KeyEvent.VK_F1:
      return 0xffbe;
    case KeyEvent.VK_F2:
      return 0xffbf;
    case KeyEvent.VK_F3:
      return 0xffc0;
    case KeyEvent.VK_F4:
      return 0xffc1;
    case KeyEvent.VK_F5:
      return 0xffc2;
    case KeyEvent.VK_F6:
      return 0xffc3;
    case KeyEvent.VK_F7:
      return 0xffc4;
    case KeyEvent.VK_F8:
      return 0xffc5;
    case KeyEvent.VK_F9:
      return 0xffc6;
    case KeyEvent.VK_F10:
      return 0xffc7;
    case KeyEvent.VK_F11:
      return 0xffc8;
    case KeyEvent.VK_F12:
      return 0xffc9;
    case KeyEvent.VK_SHIFT:
      return 0xffe1;
    case KeyEvent.VK_CONTROL:
      return 0xffe3;
    case KeyEvent.VK_META:
      return 0xffe7;
    case KeyEvent.VK_ALT:
      return 0xffe9;
    case KeyEvent.VK_ALT_GRAPH:
      return 0xffea;
    case KeyEvent.VK_BACK_QUOTE:
      return 0x0060;
    }

    return key;
  }

}
