// Copyright 2010-2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#import "mac/KeyCodeMap.h"

#include <map>

#import <Carbon/Carbon.h>

#include "base/logging.h"
#include "base/mutex.h"
#include "session/commands.pb.h"

using mozc::commands::KeyEvent;
using mozc::once_t;
using mozc::CallOnce;

#include "mac/init_kanamap.h"
#include "mac/init_specialcharmap.h"
#include "mac/init_specialkeymap.h"

static const unichar kYenMark = 0xA5;

@interface KeyCodeMap ()
// Extract Mac modifier flag bits from |flags| and set them into
// |keyEvent|.
- (void)addModifierFlags:(NSUInteger)flags
          toMozcKeyEvent:(KeyEvent *)keyEvent;

// Extract key event information from |event| of NSFlagsChanged.
// Returns YES only if the flag change should create an Mozc key
// events.
- (BOOL)handleModifierFlagsChange:(NSEvent *)event
                   toMozcKeyEvent:(KeyEvent *)keyEvent;
@end

@implementation KeyCodeMap
@synthesize inputMode = inputMode_;

- (id)init {
  CallOnce(&kOnceForKanaMap, InitKanaMap);
  CallOnce(&kOnceForSpecialKeyMap, InitSpecialKeyMap);
  CallOnce(&kOnceForSpecialCharMap, InitSpecialCharMap);
  if (kSpecialKeyMap == NULL) {
    self = nil;
    return self;
  }
  self = [super init];
  if (!self) {
    inputMode_ = ASCII;
  }
  return self;
}

- (void)addModifierFlags:(NSUInteger)flags
          toMozcKeyEvent:(KeyEvent *)keyEvent {
  if ((flags & NSShiftKeyMask)) {
    keyEvent->add_modifier_keys(KeyEvent::SHIFT);
  }
  if (flags & NSControlKeyMask) {
    keyEvent->add_modifier_keys(KeyEvent::CTRL);
  }
  if (flags & NSAlternateKeyMask) {
    keyEvent->add_modifier_keys(KeyEvent::ALT);
  }
}

- (BOOL)handleModifierFlagsChange:(NSEvent *)event
                   toMozcKeyEvent:(KeyEvent *)keyEvent {
  NSUInteger newFlags = [event modifierFlags];
  // Clear unused modifier flag bits.
  newFlags = newFlags & (NSShiftKeyMask |
                         NSControlKeyMask | NSAlternateKeyMask);
  if (~modifierFlags_ & newFlags) {
    // New modifier key is pressed: overwrite |modifierFlags_|.
    // Consider the case as follows:
    // 1. shift and control is pressed
    // 2. only control is released
    // 3. alt is newly pressed
    // At that time, modifierFlags_ should be shift+alt.
    modifierFlags_ = newFlags;
  }
  // If new modifier key is not pressed (i.e. some keys are released),
  // we do not update |modifierFlags_| at that time.  |modifierFlags_|
  // will become 0 when all modifier keys are released.

  if (newFlags != 0) {
    // The user is still pressing some modifier keys.
    return NO;
  }
  if (newFlags == 0 && modifierFlags_ == 0) {
    // The user released modifier keys but modifierFlags_ are already cleared.
    // Ex: Shift -> a (send Shift-a) -> release a -> release Shift (here)
    return NO;
  }

  [self addModifierFlags:modifierFlags_ toMozcKeyEvent:keyEvent];
  modifierFlags_ = 0;
  return YES;
}

- (BOOL)isModeSwitchingKey:(NSEvent *)event {
  NSUInteger keyCode = [event keyCode];
  return keyCode == kVK_JIS_Eisu || keyCode == kVK_JIS_Kana;
}

- (BOOL)getMozcKeyCodeFromKeyEvent:(NSEvent *)event
                    toMozcKeyEvent:(KeyEvent *)keyEvent {
  // This method uses |charactersIgnoringModifiers| basically but uses
  // |characters| if its modifier is only Shift.
  // For example:
  // \C-a   => CTRL + a  where characters = "\x01"
  // \S-a   => A         where characters = "\x41"
  // \C-S-a => CTRL + SHIFT + a where characters = "\x61"
  // \C-[   => Ctrl + [  where characters = "\x1b"
  // \S-[   => {         where characters = "\x7b"
  // \C-S-[ => CTRL + SHIFT + [ where characters = "\x5b"
  //
  // The main reason to do this is to avoid the confusion between \C-[
  // and ESC.
  //
  // There should be discussion like \C-S-a => CTRL + A instead of
  // CTRL + SHIFT + a, but we're not doing this currently because
  // Mozc must have keyboard layout information like "\S-[ => {" for
  // the case of input is symbol.

  if ([event type] == NSFlagsChanged) {
    return [self handleModifierFlagsChange:event toMozcKeyEvent:keyEvent];
  } else {
    modifierFlags_ = 0;
  }

  NSString *inputString = [event characters];
  NSString *inputStringRaw = [event charactersIgnoringModifiers];
  if ([inputString length] == 0) {
    return NO;
  }

  NSUInteger nsModifiers = [event modifierFlags];
  // strip caps lock effects.
  nsModifiers &= (~NSAlphaShiftKeyMask & NSDeviceIndependentModifierFlagsMask);
  unsigned short keyCode = [event keyCode];
  unichar inputChar = [((nsModifiers == NSShiftKeyMask) ?
                        inputString : inputStringRaw) characterAtIndex:0];
  map<unsigned short, KeyEvent::SpecialKey>::const_iterator sp_iter =
      kSpecialKeyMap->find(keyCode);
  if (sp_iter != kSpecialKeyMap->end()) {
    keyEvent->set_special_key(sp_iter->second);
  } else {
    map<unichar, KeyEvent::SpecialKey>::const_iterator spc_iter =
        kSpecialCharMap->find(inputChar);
    if (spc_iter != kSpecialCharMap->end()) {
      keyEvent->set_special_key(spc_iter->second);
    } else if (isgraph(inputChar)) {
      keyEvent->set_key_code(inputChar);
    } else if (inputChar == kYenMark) {
      keyEvent->set_key_code('\\');
    }

    // fill kana "key_string" if mode is kana.
    if (inputMode_ == KANA && !keyEvent->has_special_key()) {
      map<unsigned short, const char *>::const_iterator kana_iter;
      if (nsModifiers == NSShiftKeyMask && kKanaMapShift &&
          (kana_iter = kKanaMapShift->find(keyCode)) != kKanaMapShift->end()) {
        keyEvent->set_key_string(kana_iter->second);
      } else if (kKanaMap &&
                 (kana_iter = kKanaMap->find(keyCode)) != kKanaMap->end()) {
        keyEvent->set_key_string(kana_iter->second);
      }
    }
  }

  if (nsModifiers & NSCommandKeyMask) {
    // When command key is pressed, it is not a mozc key command.
    // Just ignore.
    return NO;
  }

#ifdef DEBUG
  // We enclose this logging with DEBUG explicitly because we found
  // that stringWithFormat is sometimes not trustworthy and DLOG(INFO)
  // will compute the string-to-be-logged even in production.
  LOG(INFO) << [[NSString stringWithFormat:@"%@", event] UTF8String]
            << " -> " << keyEvent->DebugString();
#endif

  if (nsModifiers == NSShiftKeyMask && !keyEvent->has_special_key()) {
    // If only the modifier is Shift and |keyEvent| is not normal key,
    // don't put any modifiers.
    return YES;
  }
  [self addModifierFlags:nsModifiers toMozcKeyEvent:keyEvent];
  return YES;
}

@end
