/*
 * ConnectBot: simple, powerful, open-source SSH client for Android
 * Copyright 2010 Kenny Root, Jeffrey Sharkey
 *
 * Licensed 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 org.connectbot.service;

import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.content.res.Configuration;
import android.text.ClipboardManager;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnKeyListener;

import com.googlecode.android_scripting.Log;

import de.mud.terminal.VDUBuffer;
import de.mud.terminal.vt320;

import java.io.IOException;

import org.connectbot.TerminalView;
import org.connectbot.transport.AbsTransport;
import org.connectbot.util.PreferenceConstants;
import org.connectbot.util.SelectionArea;

/**
 * @author kenny
 * @author modified by raaar
 */
public class TerminalKeyListener implements OnKeyListener, OnSharedPreferenceChangeListener {

  public final static int META_CTRL_ON = 0x01;
  public final static int META_CTRL_LOCK = 0x02;
  public final static int META_ALT_ON = 0x04;
  public final static int META_ALT_LOCK = 0x08;
  public final static int META_SHIFT_ON = 0x10;
  public final static int META_SHIFT_LOCK = 0x20;
  public final static int META_SLASH = 0x40;
  public final static int META_TAB = 0x80;

  // The bit mask of momentary and lock states for each
  public final static int META_CTRL_MASK = META_CTRL_ON | META_CTRL_LOCK;
  public final static int META_ALT_MASK = META_ALT_ON | META_ALT_LOCK;
  public final static int META_SHIFT_MASK = META_SHIFT_ON | META_SHIFT_LOCK;

  // All the transient key codes
  public final static int META_TRANSIENT = META_CTRL_ON | META_ALT_ON | META_SHIFT_ON;

  public final static int KEYBOARD_META_CTRL_ON = 0x1000; // Ctrl key mask for API 11+
  private final TerminalManager manager;
  private final TerminalBridge bridge;
  private final VDUBuffer buffer;

  protected KeyCharacterMap keymap = KeyCharacterMap.load(KeyCharacterMap.BUILT_IN_KEYBOARD);

  private String keymode = null;
  private boolean hardKeyboard = false;

  private int metaState = 0;

  private ClipboardManager clipboard = null;
  private boolean selectingForCopy = false;
  private final SelectionArea selectionArea;

  private String encoding;

  public TerminalKeyListener(TerminalManager manager, TerminalBridge bridge, VDUBuffer buffer,
      String encoding) {
    this.manager = manager;
    this.bridge = bridge;
    this.buffer = buffer;
    this.encoding = encoding;

    selectionArea = new SelectionArea();

    manager.registerOnSharedPreferenceChangeListener(this);

    hardKeyboard =
        (manager.getResources().getConfiguration().keyboard == Configuration.KEYBOARD_QWERTY);

    updateKeymode();
  }

  /**
   * Handle onKey() events coming down from a {@link TerminalView} above us. Modify the keys to make
   * more sense to a host then pass it to the transport.
   */
  public boolean onKey(View v, int keyCode, KeyEvent event) {
    try {
      final boolean hardKeyboardHidden = manager.isHardKeyboardHidden();

      AbsTransport transport = bridge.getTransport();

      // Ignore all key-up events except for the special keys
      if (event.getAction() == KeyEvent.ACTION_UP) {
        // There's nothing here for virtual keyboard users.
        if (!hardKeyboard || (hardKeyboard && hardKeyboardHidden)) {
          return false;
        }

        // skip keys if we aren't connected yet or have been disconnected
        if (transport == null || !transport.isSessionOpen()) {
          return false;
        }

        if (PreferenceConstants.KEYMODE_RIGHT.equals(keymode)) {
          if (keyCode == KeyEvent.KEYCODE_ALT_RIGHT && (metaState & META_SLASH) != 0) {
            metaState &= ~(META_SLASH | META_TRANSIENT);
            transport.write('/');
            return true;
          } else if (keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT && (metaState & META_TAB) != 0) {
            metaState &= ~(META_TAB | META_TRANSIENT);
            transport.write(0x09);
            return true;
          }
        } else if (PreferenceConstants.KEYMODE_LEFT.equals(keymode)) {
          if (keyCode == KeyEvent.KEYCODE_ALT_LEFT && (metaState & META_SLASH) != 0) {
            metaState &= ~(META_SLASH | META_TRANSIENT);
            transport.write('/');
            return true;
          } else if (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT && (metaState & META_TAB) != 0) {
            metaState &= ~(META_TAB | META_TRANSIENT);
            transport.write(0x09);
            return true;
          }
        }

        return false;
      }

      if (keyCode == KeyEvent.KEYCODE_BACK && transport != null) {
        bridge.dispatchDisconnect(!transport.isSessionOpen());
        return true;
      }

      // check for terminal resizing keys
      if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
        bridge.increaseFontSize();
        return true;
      } else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
        bridge.decreaseFontSize();
        return true;
      }

      // skip keys if we aren't connected yet or have been disconnected
      if (transport == null || !transport.isSessionOpen()) {
        return false;
      }

      bridge.resetScrollPosition();

      boolean printing = (keymap.isPrintingKey(keyCode) || keyCode == KeyEvent.KEYCODE_SPACE);

      // otherwise pass through to existing session
      // print normal keys
      if (printing) {
        int curMetaState = event.getMetaState();

        metaState &= ~(META_SLASH | META_TAB);

        if ((metaState & META_SHIFT_MASK) != 0) {
          curMetaState |= KeyEvent.META_SHIFT_ON;
          metaState &= ~META_SHIFT_ON;
          bridge.redraw();
        }

        if ((metaState & META_ALT_MASK) != 0) {
          curMetaState |= KeyEvent.META_ALT_ON;
          metaState &= ~META_ALT_ON;
          bridge.redraw();
        }

        int key = keymap.get(keyCode, curMetaState);
        if ((curMetaState & KEYBOARD_META_CTRL_ON) != 0) {
          metaState |= META_CTRL_ON;
          key = keymap.get(keyCode, 0);
        }

        if ((metaState & META_CTRL_MASK) != 0) {
          metaState &= ~META_CTRL_ON;
          bridge.redraw();

          if ((!hardKeyboard || (hardKeyboard && hardKeyboardHidden)) && sendFunctionKey(keyCode)) {
            return true;
          }

          // Support CTRL-a through CTRL-z
          if (key >= 0x61 && key <= 0x7A) {
            key -= 0x60;
          } else if (key >= 0x41 && key <= 0x5F) {
            key -= 0x40;
          } else if (key == 0x20) {
            key = 0x00;
          } else if (key == 0x3F) {
            key = 0x7F;
          }
        }

        // handle pressing f-keys
        // Doesn't work properly with asus keyboards... may never have worked. RM 09-Apr-2012
        /*
         * if ((hardKeyboard && !hardKeyboardHidden) && (curMetaState & KeyEvent.META_SHIFT_ON) != 0
         * && sendFunctionKey(keyCode)) { return true; }
         */

        if (key < 0x80) {
          transport.write(key);
        } else {
          // TODO write encoding routine that doesn't allocate each time
          transport.write(new String(Character.toChars(key)).getBytes(encoding));
        }

        return true;
      }

      if (keyCode == KeyEvent.KEYCODE_UNKNOWN && event.getAction() == KeyEvent.ACTION_MULTIPLE) {
        byte[] input = event.getCharacters().getBytes(encoding);
        transport.write(input);
        return true;
      }

      // try handling keymode shortcuts
      if (hardKeyboard && !hardKeyboardHidden && event.getRepeatCount() == 0) {
        if (PreferenceConstants.KEYMODE_RIGHT.equals(keymode)) {
          switch (keyCode) {
          case KeyEvent.KEYCODE_ALT_RIGHT:
            metaState |= META_SLASH;
            return true;
          case KeyEvent.KEYCODE_SHIFT_RIGHT:
            metaState |= META_TAB;
            return true;
          case KeyEvent.KEYCODE_SHIFT_LEFT:
            metaPress(META_SHIFT_ON);
            return true;
          case KeyEvent.KEYCODE_ALT_LEFT:
            metaPress(META_ALT_ON);
            return true;
          }
        } else if (PreferenceConstants.KEYMODE_LEFT.equals(keymode)) {
          switch (keyCode) {
          case KeyEvent.KEYCODE_ALT_LEFT:
            metaState |= META_SLASH;
            return true;
          case KeyEvent.KEYCODE_SHIFT_LEFT:
            metaState |= META_TAB;
            return true;
          case KeyEvent.KEYCODE_SHIFT_RIGHT:
            metaPress(META_SHIFT_ON);
            return true;
          case KeyEvent.KEYCODE_ALT_RIGHT:
            metaPress(META_ALT_ON);
            return true;
          }
        } else {
          switch (keyCode) {
          case KeyEvent.KEYCODE_ALT_LEFT:
          case KeyEvent.KEYCODE_ALT_RIGHT:
            metaPress(META_ALT_ON);
            return true;
          case KeyEvent.KEYCODE_SHIFT_LEFT:
          case KeyEvent.KEYCODE_SHIFT_RIGHT:
            metaPress(META_SHIFT_ON);
            return true;
          }
        }
      }

      // look for special chars
      switch (keyCode) {
      case KeyEvent.KEYCODE_CAMERA:

        // check to see which shortcut the camera button triggers
        String camera =
            manager.getStringParameter(PreferenceConstants.CAMERA,
                PreferenceConstants.CAMERA_CTRLA_SPACE);
        if (PreferenceConstants.CAMERA_CTRLA_SPACE.equals(camera)) {
          transport.write(0x01);
          transport.write(' ');
        } else if (PreferenceConstants.CAMERA_CTRLA.equals(camera)) {
          transport.write(0x01);
        } else if (PreferenceConstants.CAMERA_ESC.equals(camera)) {
          ((vt320) buffer).keyTyped(vt320.KEY_ESCAPE, ' ', 0);
        } else if (PreferenceConstants.CAMERA_ESC_A.equals(camera)) {
          ((vt320) buffer).keyTyped(vt320.KEY_ESCAPE, ' ', 0);
          transport.write('a');
        }

        break;

      case KeyEvent.KEYCODE_DEL:
        ((vt320) buffer).keyPressed(vt320.KEY_BACK_SPACE, ' ', getStateForBuffer());
        metaState &= ~META_TRANSIENT;
        return true;
      case KeyEvent.KEYCODE_ENTER:
        ((vt320) buffer).keyTyped(vt320.KEY_ENTER, ' ', 0);
        metaState &= ~META_TRANSIENT;
        return true;

      case KeyEvent.KEYCODE_DPAD_LEFT:
        if (selectingForCopy) {
          selectionArea.decrementColumn();
          bridge.redraw();
        } else {
          ((vt320) buffer).keyPressed(vt320.KEY_LEFT, ' ', getStateForBuffer());
          metaState &= ~META_TRANSIENT;
          bridge.tryKeyVibrate();
        }
        return true;

      case KeyEvent.KEYCODE_DPAD_UP:
        if (selectingForCopy) {
          selectionArea.decrementRow();
          bridge.redraw();
        } else {
          ((vt320) buffer).keyPressed(vt320.KEY_UP, ' ', getStateForBuffer());
          metaState &= ~META_TRANSIENT;
          bridge.tryKeyVibrate();
        }
        return true;

      case KeyEvent.KEYCODE_DPAD_DOWN:
        if (selectingForCopy) {
          selectionArea.incrementRow();
          bridge.redraw();
        } else {
          ((vt320) buffer).keyPressed(vt320.KEY_DOWN, ' ', getStateForBuffer());
          metaState &= ~META_TRANSIENT;
          bridge.tryKeyVibrate();
        }
        return true;

      case KeyEvent.KEYCODE_DPAD_RIGHT:
        if (selectingForCopy) {
          selectionArea.incrementColumn();
          bridge.redraw();
        } else {
          ((vt320) buffer).keyPressed(vt320.KEY_RIGHT, ' ', getStateForBuffer());
          metaState &= ~META_TRANSIENT;
          bridge.tryKeyVibrate();
        }
        return true;

      case KeyEvent.KEYCODE_DPAD_CENTER:
        if (selectingForCopy) {
          if (selectionArea.isSelectingOrigin()) {
            selectionArea.finishSelectingOrigin();
          } else {
            if (clipboard != null) {
              // copy selected area to clipboard
              String copiedText = selectionArea.copyFrom(buffer);

              clipboard.setText(copiedText);
              // XXX STOPSHIP
              // manager.notifyUser(manager.getString(
              // R.string.console_copy_done,
              // copiedText.length()));

              selectingForCopy = false;
              selectionArea.reset();
            }
          }
        } else {
          if ((metaState & META_CTRL_ON) != 0) {
            ((vt320) buffer).keyTyped(vt320.KEY_ESCAPE, ' ', 0);
            metaState &= ~META_CTRL_ON;
          } else {
            metaState |= META_CTRL_ON;
          }
        }

        bridge.redraw();

        return true;
      }

    } catch (IOException e) {
      Log.e("Problem while trying to handle an onKey() event", e);
      try {
        bridge.getTransport().flush();
      } catch (IOException ioe) {
        Log.d("Our transport was closed, dispatching disconnect event");
        bridge.dispatchDisconnect(false);
      }
    } catch (NullPointerException npe) {
      Log.d("Input before connection established ignored.");
      return true;
    }

    return false;
  }

  /**
   * @param keyCode
   * @return successful
   */
  private boolean sendFunctionKey(int keyCode) {
    switch (keyCode) {
    case KeyEvent.KEYCODE_1:
      ((vt320) buffer).keyPressed(vt320.KEY_F1, ' ', 0);
      return true;
    case KeyEvent.KEYCODE_2:
      ((vt320) buffer).keyPressed(vt320.KEY_F2, ' ', 0);
      return true;
    case KeyEvent.KEYCODE_3:
      ((vt320) buffer).keyPressed(vt320.KEY_F3, ' ', 0);
      return true;
    case KeyEvent.KEYCODE_4:
      ((vt320) buffer).keyPressed(vt320.KEY_F4, ' ', 0);
      return true;
    case KeyEvent.KEYCODE_5:
      ((vt320) buffer).keyPressed(vt320.KEY_F5, ' ', 0);
      return true;
    case KeyEvent.KEYCODE_6:
      ((vt320) buffer).keyPressed(vt320.KEY_F6, ' ', 0);
      return true;
    case KeyEvent.KEYCODE_7:
      ((vt320) buffer).keyPressed(vt320.KEY_F7, ' ', 0);
      return true;
    case KeyEvent.KEYCODE_8:
      ((vt320) buffer).keyPressed(vt320.KEY_F8, ' ', 0);
      return true;
    case KeyEvent.KEYCODE_9:
      ((vt320) buffer).keyPressed(vt320.KEY_F9, ' ', 0);
      return true;
    case KeyEvent.KEYCODE_0:
      ((vt320) buffer).keyPressed(vt320.KEY_F10, ' ', 0);
      return true;
    default:
      return false;
    }
  }

  /**
   * Handle meta key presses where the key can be locked on.
   * <p>
   * 1st press: next key to have meta state<br />
   * 2nd press: meta state is locked on<br />
   * 3rd press: disable meta state
   * 
   * @param code
   */
  private void metaPress(int code) {
    if ((metaState & (code << 1)) != 0) {
      metaState &= ~(code << 1);
    } else if ((metaState & code) != 0) {
      metaState &= ~code;
      metaState |= code << 1;
    } else {
      metaState |= code;
    }
    bridge.redraw();
  }

  public void setTerminalKeyMode(String keymode) {
    this.keymode = keymode;
  }

  private int getStateForBuffer() {
    int bufferState = 0;

    if ((metaState & META_CTRL_MASK) != 0) {
      bufferState |= vt320.KEY_CONTROL;
    }
    if ((metaState & META_SHIFT_MASK) != 0) {
      bufferState |= vt320.KEY_SHIFT;
    }
    if ((metaState & META_ALT_MASK) != 0) {
      bufferState |= vt320.KEY_ALT;
    }

    return bufferState;
  }

  public int getMetaState() {
    return metaState;
  }

  public void setClipboardManager(ClipboardManager clipboard) {
    this.clipboard = clipboard;
  }

  public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
    if (PreferenceConstants.KEYMODE.equals(key)) {
      updateKeymode();
    }
  }

  private void updateKeymode() {
    keymode =
        manager.getStringParameter(PreferenceConstants.KEYMODE, PreferenceConstants.KEYMODE_RIGHT);
  }

  public void setCharset(String encoding) {
    this.encoding = encoding;
  }
}
