// 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/GoogleJapaneseInputController.h"

#import <Carbon/Carbon.h>
#import <Cocoa/Cocoa.h>
#import <InputMethodKit/IMKInputController.h>
#import <InputMethodKit/IMKServer.h>

#include <unistd.h>

#include <cstdlib>
#include <set>

#import "mac/GoogleJapaneseInputControllerInterface.h"
#import "mac/GoogleJapaneseInputServer.h"
#import "mac/KeyCodeMap.h"

#include "base/const.h"
#include "base/logging.h"
#include "base/mac_process.h"
#include "base/mac_util.h"
#include "base/mutex.h"
#include "base/process.h"
#include "base/util.h"
#include "client/client.h"
#include "config/config.pb.h"
#include "ipc/ipc.h"
#include "renderer/renderer_client.h"
#include "session/commands.pb.h"
#include "session/ime_switch_util.h"

using mozc::commands::Candidates;
using mozc::commands::Capability;
using mozc::commands::CompositionMode;
using mozc::commands::Input;
using mozc::commands::KeyEvent;
using mozc::commands::Output;
using mozc::commands::Preedit;
using mozc::commands::RendererCommand;
using mozc::commands::SessionCommand;
using mozc::config::Config;
using mozc::config::ImeSwitchUtil;
using mozc::kProductNameInEnglish;
using mozc::once_t;
using mozc::CallOnce;
using mozc::MacProcess;

namespace {
// set of bundle IDs of applications on which Mozc should not open urls.
const set<string> *gNoOpenLinkApps = NULL;
// The mapping from the CompositionMode enum to the actual id string
// of composition modes.
const map<CompositionMode, NSString *> *gModeIdMap = NULL;
const set<string> *gNoSelectedRangeApps = NULL;
const set<string> *gNoDisplayModeSwitchApps = NULL;
const set<string> *gNoSurroundingTextApps = NULL;

// TODO(horo): This value should be get from system configuration.
//  DoubleClickInterval can be get from NSEvent (MacOSX ver >= 10.6)
const NSTimeInterval kDoubleTapInterval = 0.5;

const int kMaxSurroundingLength = 20;
// In some apllications when the client's text length is large, getting the
// surrounding text takes too much time. So we set this limitation.
const int kGetSurroundingTextClientLengthLimit = 1000;

NSString *GetLabelForSuffix(const string &suffix) {
  string label = mozc::MacUtil::GetLabelForSuffix(suffix);
  return [[NSString stringWithUTF8String:label.c_str()] retain];
}

CompositionMode GetCompositionMode(NSString *modeID) {
  if (modeID == NULL) {
    LOG(ERROR) << "modeID could not be initialized.";
    return mozc::commands::DIRECT;
  }

  // The name of direct input mode.  This name is determined at
  // Info.plist.  We don't use com.google... instead of
  // com.apple... because of a hack for Java Swing applications like
  // JEdit.  If we use our own IDs for those modes, such applications
  // work incorrectly for some reasons.
  //
  // The document for ID names is available at:
  // http://developer.apple.com/legacy/mac/library/documentation/Carbon/
  // Reference/Text_Services_Manager/Reference/reference.html
  if ([modeID isEqual:@"com.apple.inputmethod.Roman"]) {
    // TODO(komatsu): This should be mozc::commands::HALF_ASCII, when
    // we can handle the difference between the direct mode and the
    // half ascii mode.
    DLOG(INFO) << "com.apple.inputmethod.Roman";
    return mozc::commands::HALF_ASCII;
  }

  if ([modeID isEqual:@"com.apple.inputmethod.Japanese.Katakana"]) {
    DLOG(INFO) << "com.apple.inputmethod.Japanese.Katakana";
    return mozc::commands::FULL_KATAKANA;
  }

  if ([modeID isEqual:@"com.apple.inputmethod.Japanese.HalfWidthKana"]) {
    DLOG(INFO) << "com.apple.inputmethod.Japanese.HalfWidthKana";
    return mozc::commands::HALF_KATAKANA;
  }

  if ([modeID isEqual:@"com.apple.inputmethod.Japanese.FullWidthRoman"]) {
    DLOG(INFO) << "com.apple.inputmethod.Japanese.FullWidthRoman";
    return mozc::commands::FULL_ASCII;
  }

  if ([modeID isEqual:@"com.apple.inputmethod.Japanese"]) {
    DLOG(INFO) << "com.apple.inputmethod.Japanese";
    return mozc::commands::HIRAGANA;
  }

  LOG(ERROR) << "The code should not reach here.";
  return mozc::commands::DIRECT;
}

bool IsBannedApplication(const set<string>* bundleIdSet,
                         const string& bundleId) {
  return bundleIdSet == NULL || bundleId.empty() ||
      bundleIdSet->find(bundleId) != bundleIdSet->end();
}
}  // anonymous namespace


@implementation GoogleJapaneseInputController
#pragma mark accessors for testing
@synthesize keyCodeMap = keyCodeMap_;
@synthesize yenSignCharacter = yenSignCharacter_;
@synthesize mode = mode_;
@synthesize rendererCommand = rendererCommand_;
@synthesize replacementRange = replacementRange_;
@synthesize imkClientForTest = imkClientForTest_;
- (mozc::client::ClientInterface *)mozcClient {
  return mozcClient_;
}
- (void)setMozcClient:(mozc::client::ClientInterface *)newMozcClient {
  delete mozcClient_;
  mozcClient_ = newMozcClient;
}
- (mozc::renderer::RendererInterface *)renderer {
  return candidateController_;
}
- (void)setRenderer:(mozc::renderer::RendererInterface *)newRenderer {
  delete candidateController_;
  candidateController_ = newRenderer;
}


#pragma mark object init/dealloc
// Initializer designated in IMKInputController. see:
// http://developer.apple.com/documentation/Cocoa/Reference/IMKInputController_Class/

- (id)initWithServer:(IMKServer *)server
            delegate:(id)delegate
              client:(id)inputClient {
  self = [super initWithServer:server delegate:delegate client:inputClient];
  if (!self) {
    return self;
  }
  keyCodeMap_ = [[KeyCodeMap alloc] init];
  clientBundle_ = new(nothrow) string;
  replacementRange_ = NSMakeRange(NSNotFound, 0);
  originalString_ = [[NSMutableString alloc] init];
  composedString_ = [[NSMutableAttributedString alloc] init];
  cursorPosition_ = NSNotFound;
  mode_ = mozc::commands::DIRECT;
  checkInputMode_ = YES;
  suppressSuggestion_ = NO;
  yenSignCharacter_ = mozc::config::Config::YEN_SIGN;
  candidateController_ = new(nothrow) mozc::renderer::RendererClient;
  rendererCommand_ = new(nothrow)RendererCommand;
  mozcClient_ = mozc::client::ClientFactory::NewClient();
  imkServer_ = reinterpret_cast<id<ServerCallback> >(server);
  imkClientForTest_ = nil;
  lastKeyDownTime_ = 0;
  lastKeyCode_ = 0;

  // We don't check the return value of NSBundle because it fails during tests.
  [NSBundle loadNibNamed:@"Config" owner:self];
  if (!originalString_ || !composedString_ || !candidateController_ ||
      !rendererCommand_ || !mozcClient_ || !clientBundle_) {
    [self release];
    self = nil;
  } else {
    DLOG(INFO) << [[NSString stringWithFormat:@"initWithServer: %@ %@ %@",
                             server, delegate, inputClient] UTF8String];
    if (!candidateController_->Activate()) {
      LOG(ERROR) << "Cannot activate renderer";
      delete candidateController_;
      candidateController_ = NULL;
    }
    [self setupClientBundle:inputClient];
    [self setupCapability];
    RendererCommand::ApplicationInfo *applicationInfo =
        rendererCommand_->mutable_application_info();
    applicationInfo->set_process_id(::getpid());
    // thread_id and receiver_handle are not used currently in Mac but
    // set some values to prevent warning.
    applicationInfo->set_thread_id(0);
    applicationInfo->set_receiver_handle(0);
  }

  return self;
}

- (void)dealloc {
  [keyCodeMap_ release];
  [originalString_ release];
  [composedString_ release];
  [imkClientForTest_ release];
  delete clientBundle_;
  delete candidateController_;
  delete mozcClient_;
  delete rendererCommand_;
  DLOG(INFO) << "dealloc server";
  [super dealloc];
}

- (id)client {
  if (imkClientForTest_) {
    return imkClientForTest_;
  }
  return [super client];
}

- (NSMenu*)menu {
  return menu_;
}

+ (void)initializeConstants {
  set<string> *noOpenlinkApps = new(nothrow) set<string>;
  if (noOpenlinkApps) {
    // should not open links during screensaver.
    noOpenlinkApps->insert("com.apple.securityagent");
    gNoOpenLinkApps = noOpenlinkApps;
  }

  map<CompositionMode, NSString *> *newMap =
      new(nothrow) map<CompositionMode, NSString *>;
  if (newMap) {
    (*newMap)[mozc::commands::DIRECT] = GetLabelForSuffix("Roman");
    (*newMap)[mozc::commands::HIRAGANA] = GetLabelForSuffix("base");
    (*newMap)[mozc::commands::FULL_KATAKANA] = GetLabelForSuffix("Katakana");
    (*newMap)[mozc::commands::HALF_ASCII] = GetLabelForSuffix("Roman");
    (*newMap)[mozc::commands::FULL_ASCII] = GetLabelForSuffix("FullWidthRoman");
    (*newMap)[mozc::commands::HALF_KATAKANA] =
        GetLabelForSuffix("FullWidthRoman");
    gModeIdMap = newMap;
  }

  set<string> *noSelectedRangeApps = new(nothrow) set<string>;
  if (noSelectedRangeApps) {
    // Do not call selectedRange: method for the following
    // applications because it could lead to application crash.
    noSelectedRangeApps->insert("com.microsoft.Excel");
    noSelectedRangeApps->insert("com.microsoft.Powerpoint");
    noSelectedRangeApps->insert("com.microsoft.Word");
    gNoSelectedRangeApps = noSelectedRangeApps;
  }

  // Do not call selectInputMode: method for the following
  // applications because it could cause some unexpected behavior.
  // MS-Word: When the display mode goes to ASCII but there is no
  // compositions, it goes to direct input mode instead of Half-ASCII
  // mode.  When the first composition character is alphanumeric (such
  // like pressing Shift-A at first), that character is directly
  // inserted into application instead of composition starting "A".
  set<string> *noDisplayModeSwitchApps = new(nothrow) set<string>;
  if (noDisplayModeSwitchApps) {
    noDisplayModeSwitchApps->insert("com.microsoft.Word");
    gNoDisplayModeSwitchApps = noDisplayModeSwitchApps;
  }

  set<string> *noSurroundingTextApps = new(nothrow) set<string>;
  if (noSurroundingTextApps) {
    // Disables the surrounding text feature for the following application
    // because calling attributedSubstringFromRange to it is very heavy.
    noSurroundingTextApps->insert("com.evernote.Evernote");
    gNoSurroundingTextApps = noSurroundingTextApps;
  }
}

#pragma mark IMKStateSetting Protocol
// Currently it just ignores the following methods:
//   Modes, showPreferences, valueForTag
// They are described at
// http://developer.apple.com/documentation/Cocoa/Reference/IMKStateSetting_Protocol/

- (void)activateServer:(id)sender {
  [super activateServer:sender];
  checkInputMode_ = YES;
  if (rendererCommand_->visible() && candidateController_) {
    candidateController_->ExecCommand(*rendererCommand_);
  }
  [self handleConfig];
  [imkServer_ setCurrentController:self];

  string window_name, window_owner;
  if (mozc::MacUtil::GetFrontmostWindowNameAndOwner(&window_name,
                                                    &window_owner)) {
    DLOG(INFO) << "frontmost window name: \"" << window_name << "\" "
               << "owner: \"" << window_owner << "\"";
    if (mozc::MacUtil::IsSuppressSuggestionWindow(window_name, window_owner)) {
      suppressSuggestion_ = YES;
    } else {
      suppressSuggestion_ = NO;
    }
  }

  DLOG(INFO) << kProductNameInEnglish << " client (" << self
             << "): activated for " << sender;
  DLOG(INFO) << "sender bundleID: " << *clientBundle_;
}

- (void)deactivateServer:(id)sender {
  RendererCommand clearCommand;
  clearCommand.set_type(RendererCommand::UPDATE);
  clearCommand.set_visible(false);
  clearCommand.clear_output();
  if (candidateController_) {
    candidateController_->ExecCommand(clearCommand);
  }
  DLOG(INFO) << kProductNameInEnglish << " client (" << self
             << "): deactivated";
  DLOG(INFO) << "sender bundleID: " << *clientBundle_;
  [super deactivateServer:sender];
}

- (NSUInteger)recognizedEvents:(id)sender {
  // Because we want to handle single Shift key pressing later, now I
  // turned on NSFlagsChanged also.
  return NSKeyDownMask | NSFlagsChangedMask;
}

// This method is called when a user changes the input mode.
- (void)setValue:(id)value forTag:(long)tag client:(id)sender {
  CompositionMode new_mode = GetCompositionMode(value);

  if (new_mode == mozc::commands::HALF_ASCII && [composedString_ length] == 0) {
    new_mode = mozc::commands::DIRECT;
  }

  [self switchMode:new_mode client:sender];
  [self handleConfig];
  [super setValue:value forTag:tag client:sender];
}


#pragma mark internal methods

- (void)handleConfig {
  // Get the config and set client-side behaviors
  Config config;
  if (!mozcClient_->GetConfig(&config)) {
    LOG(ERROR) << "Cannot obtain the current config";
    return;
  }

  InputMode input_mode = ASCII;
  if (config.preedit_method() == Config::KANA) {
    input_mode = KANA;
  }
  [keyCodeMap_ setInputMode:input_mode];
  yenSignCharacter_ = config.yen_sign_character();

  if (config.use_japanese_layout()) {
    // Apple does not have "Japanese" layout actually -- here sets
    // "US" layout, which means US-ASCII layout or JIS layout
    // depending on which type of keyboard is actually connected.
    [[self client] overrideKeyboardWithKeyboardNamed:@"com.apple.keylayout.US"];
  }
}

- (void)setupClientBundle:(id)sender {
  NSString *bundleIdentifier = [sender bundleIdentifier];
  if (bundleIdentifier != nil && [bundleIdentifier length] > 0) {
    clientBundle_->assign([bundleIdentifier UTF8String]);
  }
}

- (void)setupCapability {
  Capability capability;

  if (IsBannedApplication(gNoSelectedRangeApps, *clientBundle_)) {
    capability.set_text_deletion(Capability::NO_TEXT_DELETION_CAPABILITY);
  } else {
    capability.set_text_deletion(Capability::DELETE_PRECEDING_TEXT);
  }

  mozcClient_->set_client_capability(capability);
}

// Mode changes to direct and clean up the status.
- (void)switchModeToDirect:(id)sender {
  mode_ = mozc::commands::DIRECT;
  DLOG(INFO) << "Mode switch: HIRAGANA, KATAKANA, etc. -> DIRECT";
  KeyEvent keyEvent;
  Output output;
  keyEvent.set_special_key(mozc::commands::KeyEvent::OFF);
  mozcClient_->SendKey(keyEvent, &output);
  if (output.has_result()) {
    [self commitText:output.result().value().c_str() client:sender];
  }
  if ([composedString_ length] > 0) {
    [self updateComposedString:NULL];
    [self clearCandidates];
  }
}

// change the mode to the new mode and turn-on the IME if necessary.
- (void)switchModeInternal:(CompositionMode)new_mode {
  if (mode_ == mozc::commands::DIRECT) {
    // Input mode changes from direct to an active mode.
    DLOG(INFO) << "Mode switch: DIRECT -> HIRAGANA, KATAKANA, etc.";
    KeyEvent keyEvent;
    Output output;
    keyEvent.set_special_key(mozc::commands::KeyEvent::ON);
    mozcClient_->SendKey(keyEvent, &output);
  }

  if (mode_ != new_mode) {
    // Switch input mode.
    DLOG(INFO) << "Switch input mode.";
    SessionCommand command;
    command.set_type(mozc::commands::SessionCommand::SWITCH_INPUT_MODE);
    command.set_composition_mode(new_mode);
    Output output;
    mozcClient_->SendCommand(command, &output);
    mode_ = new_mode;
  }
}

- (void)switchMode:(CompositionMode)new_mode client:(id)sender {
  if (mode_ == new_mode) {
    return;
  }
  if (mode_ != mozc::commands::DIRECT && new_mode == mozc::commands::DIRECT) {
    [self switchModeToDirect:sender];
  } else if (new_mode != mozc::commands::DIRECT) {
    [self switchModeInternal:new_mode];
  }
}

- (void)switchDisplayMode {
  if (gModeIdMap == NULL) {
    LOG(ERROR) << "gModeIdMap is not initialized correctly.";
    return;
  }
  if (IsBannedApplication(gNoDisplayModeSwitchApps, *clientBundle_)) {
    return;
  }

  map<CompositionMode, NSString *>::const_iterator it = gModeIdMap->find(mode_);
  if (it == gModeIdMap->end()) {
    LOG(ERROR) << "mode: " << mode_ << " is invalid";
    return;
  }

  [[self client] selectInputMode:it->second];
}

- (void)commitText:(const char *)text client:(id)sender {
  if (text == NULL) {
    return;
  }

  [sender insertText:[NSString stringWithUTF8String:text]
    replacementRange:replacementRange_];
  replacementRange_ = NSMakeRange(NSNotFound, 0);
}

- (void)launchWordRegisterTool:(id)client {
  ::setenv(mozc::kWordRegisterEnvironmentName, "", 1);
  if (!IsBannedApplication(gNoSelectedRangeApps, *clientBundle_)) {
    NSRange selectedRange = [client selectedRange];
    if (selectedRange.location != NSNotFound &&
        selectedRange.length != NSNotFound &&
        selectedRange.length > 0) {
      NSString *text =
        [[client attributedSubstringFromRange:selectedRange] string];
      if (text != nil) {
        :: setenv(mozc::kWordRegisterEnvironmentName, [text UTF8String], 1);
      }
    }
  }
  MacProcess::LaunchMozcTool("word_register_dialog");
}

- (void)invokeReconvert:(const SessionCommand *)command client:(id)sender {
  if (IsBannedApplication(gNoSelectedRangeApps, *clientBundle_)) {
    return;
  }

  NSRange selectedRange = [sender selectedRange];
  if (selectedRange.location == NSNotFound ||
      selectedRange.length == NSNotFound) {
    // the application does not support reconversion.
    return;
  }

  DLOG(INFO) << selectedRange.location << ", " << selectedRange.length;
  SessionCommand sending_command;
  Output output;
  sending_command.CopyFrom(*command);

  if (selectedRange.length == 0) {
    // Currently no range is selected for reconversion.  Tries to
    // invoke UNDO instead.
    [self invokeUndo:sender];
    return;
  }

  if (!sending_command.has_text()) {
    NSString *text = [[sender attributedSubstringFromRange:selectedRange] string];
    if (!text) {
      return;
    }
    sending_command.set_text([text UTF8String]);
  }

  if (mozcClient_->SendCommand(sending_command, &output)) {
    replacementRange_ = selectedRange;
    [self processOutput:&output client:sender];
  }
}

- (void)invokeUndo:(id)sender {
  if (IsBannedApplication(gNoSelectedRangeApps, *clientBundle_)) {
    return;
  }

  NSRange selectedRange = [sender selectedRange];
  if (selectedRange.location == NSNotFound ||
      selectedRange.length == NSNotFound ||
      // Some applications such like iTunes does not return NSNotFound
      // range but (0, 0).  However, the range starting with negative
      // location has to be invalid, then we can reject such apps.
      selectedRange.location == 0) {
    return;
  }

  DLOG(INFO) << selectedRange.location << ", " << selectedRange.length;
  SessionCommand command;
  Output output;
  command.set_type(SessionCommand::UNDO);
  if (mozcClient_->SendCommand(command, &output)) {
    [self processOutput:&output client:sender];
  }
}

- (void)processOutput:(const mozc::commands::Output *)output client:(id)sender {
  if (output == NULL) {
    return;
  }
  if (!output->consumed()) {
    return;
  }

  DLOG(INFO) << output->DebugString();
  if (output->has_url()) {
    NSString *url = [NSString stringWithUTF8String:output->url().c_str()];
    [self openLink:[NSURL URLWithString:url]];
  }

  if (output->has_result()) {
    [self commitText:output->result().value().c_str() client:sender];
  }

  // Handles deletion range.  We do not even handle it for some
  // applications to prevent application crashes.
  if (output->has_deletion_range() &&
      !IsBannedApplication(gNoSelectedRangeApps, *clientBundle_)) {
    if ([composedString_ length] == 0 &&
        replacementRange_.location == NSNotFound) {
      NSRange selectedRange = [sender selectedRange];
      const mozc::commands::DeletionRange &deletion_range =
          output->deletion_range();
      if (selectedRange.location != NSNotFound ||
          selectedRange.length != NSNotFound ||
          selectedRange.location + deletion_range.offset() > 0) {
        // The offset is a negative value.  See session/commands.proto for
        // the details.
        selectedRange.location += deletion_range.offset();
        selectedRange.length += deletion_range.length();
        replacementRange_ = selectedRange;
      }
    } else {
      // We have to consider the case that there is already
      // composition and/or we already set the position of the
      // composition by replacementRange_.  We do nothing here at this
      // time because we already found that it will involve several
      // buggy behaviors with Carbon apps and MS Office.
      // TODO(mukai): find the right behavior.
    }
  }

  [self updateComposedString:&(output->preedit())];
  [self updateCandidates:output];

  if (output->has_mode()) {
    CompositionMode new_mode = output->mode();
    // Do not allow HALF_ASCII with empty composition.  This should be
    // handled in the converter, but just in case.
    if (new_mode == mozc::commands::HALF_ASCII &&
        (!output->has_preedit() || output->preedit().segment_size() == 0)) {
      new_mode = mozc::commands::DIRECT;
      [self switchMode:new_mode client:sender];
    }
    if (new_mode != mode_) {
      mode_ = new_mode;
      [self switchDisplayMode];
    }
  }

  if (output->has_launch_tool_mode()) {
    switch (output->launch_tool_mode()) {
      case mozc::commands::Output::CONFIG_DIALOG:
        MacProcess::LaunchMozcTool("config_dialog");
        break;
      case mozc::commands::Output::DICTIONARY_TOOL:
        MacProcess::LaunchMozcTool("dictionary_tool");
        break;
      case mozc::commands::Output::WORD_REGISTER_DIALOG:
        [self launchWordRegisterTool:sender];
        break;
      default:
        // do nothing
        break;
    }
  }

  // Handle callbacks.
  if (output->has_callback() && output->callback().has_session_command()) {
    if (output->callback().has_delay_millisec()) {
      callback_command_.CopyFrom(output->callback());
      // In the current implementation, if the subsequent key event also makes
      // callback, the second callback will be called in the timimg of the first
      // callback.
      [self performSelector:@selector(sendCallbackCommand)
                 withObject:nil
                 afterDelay:output->callback().has_delay_millisec() / 1000.0];
      return;
    }
    const SessionCommand &callback_command =
        output->callback().session_command();
    if (callback_command.type() == SessionCommand::CONVERT_REVERSE) {
      [self invokeReconvert:&callback_command client:sender];
    } else if (callback_command.type() == SessionCommand::UNDO) {
      [self invokeUndo:sender];
    } else {
      Output output_for_callback;
      if (mozcClient_->SendCommand(callback_command, &output_for_callback)) {
        [self processOutput:&output_for_callback client:sender];
      }
    }
  }
}

#pragma mark Mozc Server methods


#pragma mark IMKServerInput Protocol
// Currently GoogleJapaneseInputController uses handleEvent:client:
// method to handle key events.  It does not support inputText:client:
// nor inputText:key:modifiers:client:.
// Because GoogleJapaneseInputController does not use IMKCandidates,
// the following methods are not needed to implement:
//   candidates
//
// The meaning of these methods are described at:
// http://developer.apple.com/documentation/Cocoa/Reference/IMKServerInput_Additions/

- (id)originalString:(id)sender {
  return originalString_;
}

- (void)updateComposedString:(const Preedit *)preedit {
  // If the last and the current composed string length is 0,
  // we don't call updateComposition.
  if (([composedString_ length] == 0) &&
      ((preedit == NULL || preedit->segment_size() == 0))) {
    return;
  }

  [composedString_
    deleteCharactersInRange:NSMakeRange(0, [composedString_ length])];
  cursorPosition_ = NSNotFound;
  if (preedit != NULL) {
    cursorPosition_ = preedit->cursor();
    for (size_t i = 0; i < preedit->segment_size(); ++i) {
      NSDictionary *highlightAttributes =
          [self markForStyle:kTSMHiliteSelectedConvertedText
                     atRange:NSMakeRange(NSNotFound, 0)];
      NSDictionary *underlineAttributes =
          [self markForStyle:kTSMHiliteConvertedText
                     atRange:NSMakeRange(NSNotFound, 0)];
      const Preedit::Segment& seg = preedit->segment(i);
      NSDictionary *attr = (seg.annotation() == Preedit::Segment::HIGHLIGHT)?
          highlightAttributes : underlineAttributes;
      NSString *seg_string =
          [NSString stringWithUTF8String:seg.value().c_str()];
      NSAttributedString *seg_attributed_string =
          [[[NSAttributedString alloc]
             initWithString:seg_string attributes:attr]
            autorelease];
      [composedString_ appendAttributedString:seg_attributed_string];
    }
  }
  if ([composedString_ length] == 0) {
    [originalString_ setString:@""];
    replacementRange_ = NSMakeRange(NSNotFound, 0);
  }

  // Make composed string visible to the client applications.
  [self updateComposition];
}

- (void)commitComposition:(id)sender {
  if ([composedString_ length] == 0) {
    DLOG(INFO) << "Nothing is committed.";
    return;
  }
  [self commitText:[[composedString_ string] UTF8String] client:sender];

  SessionCommand command;
  Output output;
  command.set_type(SessionCommand::SUBMIT);
  mozcClient_->SendCommand(command, &output);
  [self clearCandidates];
  [self updateComposedString:NULL];
}

- (id)composedString:(id)sender {
  return composedString_;
}

- (void)clearCandidates {
  rendererCommand_->set_type(RendererCommand::UPDATE);
  rendererCommand_->set_visible(false);
  rendererCommand_->clear_output();
  if (candidateController_) {
    candidateController_->ExecCommand(*rendererCommand_);
  }
}

// |selecrionRange| method is defined at IMKInputController class and
// means the position of cursor actually.
- (NSRange)selectionRange {
  return (cursorPosition_ == NSNotFound) ?
      [super selectionRange] : // default behavior defined at super class
      NSMakeRange(cursorPosition_, 0);
}

- (void)delayedUpdateCandidates {
  // The candidate window position is not recalculated if the
  // candidate already appears on the screen.  Therefore, if a user
  // moves client application window by mouse, candidate window won't
  // follow the move of window.  This is done because:
  //  - some applications like Emacs or Google Chrome don't return the
  //    cursor position correctly.  The candidate window moves
  //    frequently with those application, which irritates users.
  //  - Kotoeri does this too.
  if ((!rendererCommand_->visible()) &&
      (rendererCommand_->output().candidates().candidate_size() > 0)) {
    NSRect preeditRect = NSZeroRect;
    const int32 position = rendererCommand_->output().candidates().position();
    // Some applications throws error when we call attributesForCharacterIndex.
    DLOG(INFO) << "attributesForCharacterIndex: " << position;
    @try {
      [[self client] attributesForCharacterIndex:position
                             lineHeightRectangle:&preeditRect];
    }
    @catch (NSException *exception) {
      LOG(ERROR) << "Exception from [" << *clientBundle_ << "] "
                 << [[exception name] UTF8String] << ","
                 << [[exception reason] UTF8String];
    }
    DLOG(INFO) << "  preeditRect: (("
               << preeditRect.origin.x << ", "
               << preeditRect.origin.y << "), ("
               << preeditRect.size.width << ", "
               << preeditRect.size.height << "))";
    NSScreen *baseScreen = nil;
    NSRect baseFrame = NSZeroRect;
    for (baseScreen in [NSScreen screens]) {
      baseFrame = [baseScreen frame];
      if (baseFrame.origin.x == 0 && baseFrame.origin.y == 0) {
        break;
      }
    }
    int baseHeight = baseFrame.size.height;
    rendererCommand_->mutable_preedit_rectangle()->set_left(
        preeditRect.origin.x);
    rendererCommand_->mutable_preedit_rectangle()->set_top(
        baseHeight - preeditRect.origin.y - preeditRect.size.height);
    rendererCommand_->mutable_preedit_rectangle()->set_right(
        preeditRect.origin.x + preeditRect.size.width);
    rendererCommand_->mutable_preedit_rectangle()->set_bottom(
        baseHeight - preeditRect.origin.y);
  }

  rendererCommand_->set_visible(
    rendererCommand_->output().candidates().candidate_size() > 0);
  if (candidateController_) {
    candidateController_->ExecCommand(*rendererCommand_);
  }
}

- (void)updateCandidates:(const Output *)output {
  if (output == NULL) {
    [self clearCandidates];
    return;
  }

  rendererCommand_->set_type(RendererCommand::UPDATE);
  rendererCommand_->mutable_output()->CopyFrom(*output);

  // Runs delayedUpdateCandidates in the next event loop.
  // This is because some applications like Google Docs with Chrome returns
  // incorrect cursor position if we call attributesForCharacterIndex here.
  [self performSelector:@selector(delayedUpdateCandidates)
             withObject:nil
             afterDelay:0];
}

- (void)openLink:(NSURL *)url {
  // Open a link specified by |url|.  Any opening link behavior should
  // call this method because it checks the capability of application.
  // On some application like login window of screensaver, opening
  // link behavior should not happen because it can cause some
  // security issues.
  if (!clientBundle_ || IsBannedApplication(gNoOpenLinkApps, *clientBundle_)) {
    return;
  }
  [[NSWorkspace sharedWorkspace] openURL:url];
}

- (BOOL)fillSurroundingContext:(mozc::commands::Context *)context
                        client:(id<IMKTextInput>)client {
  NSInteger totalLength = [client length];
  if (totalLength == 0 || totalLength == NSNotFound ||
      totalLength > kGetSurroundingTextClientLengthLimit) {
    return false;
  }
  NSRange selectedRange = [client selectedRange];
  if (selectedRange.location == NSNotFound ||
      selectedRange.length == NSNotFound) {
    return false;
  }
  NSRange precedingRange = NSMakeRange(0, selectedRange.location);
  if (selectedRange.location > kMaxSurroundingLength) {
    precedingRange =
        NSMakeRange(selectedRange.location - kMaxSurroundingLength,
                    kMaxSurroundingLength);
  }
  NSString *precedingString =
    [[client attributedSubstringFromRange:precedingRange] string];
  if (precedingString) {
    context->set_preceding_text([precedingString UTF8String]);
    DLOG(INFO) << "preceding_text: \"" << context->preceding_text() << "\"";
  }
  return true;
}

- (BOOL)handleEvent:(NSEvent *)event client:(id)sender {
  if ([event type] == NSCursorUpdate) {
    [self updateComposition];
    return NO;
  }
  if ([event type] != NSKeyDown && [event type] != NSFlagsChanged) {
    return NO;
  }
  // Cancels the callback.
  callback_command_.Clear();

  // Handle KANA key and EISU key.  We explicitly handles this here
  // for mode switch because some text area such like iPhoto person
  // name editor does not call setValue:forTag:client: method.
  // see: http://www.google.com/support/forum/p/ime/thread?tid=3aafb74ff71a1a69&hl=ja&fid=3aafb74ff71a1a690004aa3383bc9f5d
  if ([event type] == NSKeyDown) {
    NSTimeInterval currentTime = [[NSDate date] timeIntervalSince1970];
    const NSTimeInterval elapsedTime = currentTime - lastKeyDownTime_;
    const bool isDoubleTap = ([event keyCode] == lastKeyCode_) &&
                             (elapsedTime < kDoubleTapInterval);
    lastKeyDownTime_ = currentTime;
    lastKeyCode_ = [event keyCode];

    // these calling of switchMode: can be duplicated if the
    // application sends the setValue:forTag:client: and handleEvent:
    // at the same key event, but that's okay because switchMode:
    // method does nothing if the new mode is same as the current
    // mode.
    if ([event keyCode] == kVK_JIS_Kana) {
      [self switchMode:mozc::commands::HIRAGANA client:sender];
      [self switchDisplayMode];
      if (isDoubleTap) {
        SessionCommand command;
        command.set_type(SessionCommand::CONVERT_REVERSE);
        [self invokeReconvert:&command client:sender];
      }
    } else if ([event keyCode] == kVK_JIS_Eisu) {
      if (isDoubleTap) {
        SessionCommand command;
        command.set_type(SessionCommand::COMMIT_RAW_TEXT);
        [self sendCommand:command];
      }
      CompositionMode new_mode = ([composedString_ length] == 0) ?
          mozc::commands::DIRECT : mozc::commands::HALF_ASCII;
      [self switchMode:new_mode client:sender];
      [self switchDisplayMode];
    }
  }

  if ([keyCodeMap_ isModeSwitchingKey:event]) {
    // Special hack for Eisu/Kana keys.  Sometimes those key events
    // come to this method but we should ignore them because some
    // applications like PhotoShop is stuck.
    return YES;
  }

  // Get the Mozc key event
  KeyEvent keyEvent;
  if (![keyCodeMap_ getMozcKeyCodeFromKeyEvent:event
                    toMozcKeyEvent:&keyEvent]) {
    // Modifier flags change (not submitted to the server yet), or
    // unsupported key pressed.
    return NO;
  }

  // If the key event is turn on event, the key event has to be sent
  // to the server anyway.
  if (mode_ == mozc::commands::DIRECT &&
      !ImeSwitchUtil::IsDirectModeCommand(keyEvent)) {
    // Yen sign special hack: although the current mode is DIRECT,
    // backslash is sent instead of yen sign for JIS yen key with no
    // modifiers.  This behavior is based on the configuration.
    if ([event keyCode] == kVK_JIS_Yen &&
        [event modifierFlags] == 0 &&
        yenSignCharacter_ == mozc::config::Config::BACKSLASH) {
      [self commitText:"\\" client:sender];
      return YES;
    }
    return NO;
  }

  // Send the key event to the server actually
  Output output;

  if (isprint(keyEvent.key_code())) {
    [originalString_ appendFormat:@"%c", keyEvent.key_code()];
  }

  mozc::commands::Context context;
  if (suppressSuggestion_) {
    // TODO(komatsu, horo): Support Google Omnibox too.
    context.add_experimental_features("google_search_box");
  }
  keyEvent.set_mode(mode_);

  if ([composedString_ length] == 0 &&
      !IsBannedApplication(gNoSelectedRangeApps, *clientBundle_) &&
      !IsBannedApplication(gNoSurroundingTextApps, *clientBundle_)) {
    [self fillSurroundingContext:&context client:sender];
  }
  if (!mozcClient_->SendKeyWithContext(keyEvent, context, &output)) {
    return NO;
  }

  [self processOutput:&output client:sender];
  return output.consumed();
}

- (void)sendCallbackCommand {
  if (callback_command_.has_session_command()) {
    const SessionCommand command = callback_command_.session_command();
    callback_command_.Clear();
    [self sendCommand:command];
  }
}

#pragma mark callbacks
- (void)sendCommand:(const SessionCommand &)command {
  Output output;
  if (!mozcClient_->SendCommand(command, &output)) {
    return;
  }

  [self processOutput:&output client:[self client]];
}

- (IBAction)reconversionClicked:(id)sender {
  SessionCommand command;
  command.set_type(SessionCommand::CONVERT_REVERSE);
  [self invokeReconvert:&command client:[self client]];
}

- (IBAction)configClicked:(id)sender {
  MacProcess::LaunchMozcTool("config_dialog");
}

- (IBAction)dictionaryToolClicked:(id)sender {
  MacProcess::LaunchMozcTool("dictionary_tool");
}

- (IBAction)registerWordClicked:(id)sender {
  [self launchWordRegisterTool:[self client]];
}

- (IBAction)characterPaletteClicked:(id)sender {
  MacProcess::LaunchMozcTool("character_palette");
}

- (IBAction)handWritingClicked:(id)sender {
  MacProcess::LaunchMozcTool("hand_writing");
}

- (IBAction)aboutDialogClicked:(id)sender {
  MacProcess::LaunchMozcTool("about_dialog");
}

- (void)outputResult:(mozc::commands::Output *)output {
  if (output == NULL || !output->has_result()) {
    return;
  }
  [self commitText:output->result().value().c_str() client:[self client]];
}
@end
