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

// A class handling the converter on the session layer.

#include "session/session_converter.h"

#include <algorithm>
#include <limits>
#include <string>

#include "base/logging.h"
#include "base/port.h"
#include "base/text_normalizer.h"
#include "base/util.h"
#include "composer/composer.h"
#include "config/config.pb.h"
#include "config/config_handler.h"
#include "converter/converter_interface.h"
#include "converter/converter_util.h"
#include "converter/segments.h"
#include "session/commands.pb.h"
#include "session/internal/candidate_list.h"
#include "session/internal/session_output.h"
#include "session/session_usage_stats_util.h"
#include "transliteration/transliteration.h"
#include "usage_stats/usage_stats.h"

using mozc::usage_stats::UsageStats;

#ifdef OS_ANDROID
const bool kDefaultUseActualConverterForRealtimeConversion = false;
#else
const bool kDefaultUseActualConverterForRealtimeConversion = true;
#endif  // OS_ANDROID

DEFINE_bool(use_actual_converter_for_realtime_conversion,
            kDefaultUseActualConverterForRealtimeConversion,
            "If true, use the actual (non-immutable) converter for real "
            "time conversion.");

namespace mozc {
namespace session {

namespace {

using mozc::commands::Request;
using mozc::config::Config;
using mozc::config::ConfigHandler;

const size_t kDefaultMaxHistorySize = 3;

void SetPresentationMode(bool enabled) {
  Config config;
  ConfigHandler::GetConfig(&config);
  config.set_presentation_mode(enabled);
  ConfigHandler::SetConfig(config);
}

void SetIncognitoMode(bool enabled) {
  Config config;
  ConfigHandler::GetConfig(&config);
  config.set_incognito_mode(enabled);
  ConfigHandler::SetConfig(config);
}

}  // namespace

const size_t SessionConverter::kConsumedAllCharacters =
    numeric_limits<size_t>::max();

SessionConverter::SessionConverter(const ConverterInterface *converter,
                                   const Request *request)
    : SessionConverterInterface(),
      state_(COMPOSITION),
      converter_(converter),
      segments_(new Segments),
      segment_index_(0),
      result_(new commands::Result),
      candidate_list_(new CandidateList(true)),
      candidate_list_visible_(false),
      request_(request),
      client_revision_(0) {
  conversion_preferences_.use_history = true;
  conversion_preferences_.max_history_size = kDefaultMaxHistorySize;
  conversion_preferences_.request_suggestion = true;
  operation_preferences_.use_cascading_window = true;
  operation_preferences_.candidate_shortcuts.clear();
  candidate_list_->set_page_size(request->candidate_page_size());
}

SessionConverter::~SessionConverter() {}

void SessionConverter::SetOperationPreferences(
    const OperationPreferences &preferences) {
  operation_preferences_.use_cascading_window =
      preferences.use_cascading_window;
  operation_preferences_.candidate_shortcuts =
      preferences.candidate_shortcuts;
}

bool SessionConverter::CheckState(
    SessionConverterInterface::States states) const {
  return ((state_ & states) != NO_STATE);
}

bool SessionConverter::IsActive() const {
  return CheckState(SUGGESTION | PREDICTION | CONVERSION);
}

const ConversionPreferences &SessionConverter::conversion_preferences() const {
  return conversion_preferences_;
}

bool SessionConverter::Convert(const composer::Composer &composer) {
  return ConvertWithPreferences(composer, conversion_preferences_);
}

bool SessionConverter::ConvertWithPreferences(
    const composer::Composer &composer,
    const ConversionPreferences &preferences) {
  DCHECK(CheckState(COMPOSITION | SUGGESTION | CONVERSION));

  segments_->set_request_type(Segments::CONVERSION);
  SetConversionPreferences(preferences, segments_.get());

  const ConversionRequest conversion_request(&composer, request_);
  if (!converter_->StartConversionForRequest(conversion_request,
                                             segments_.get())) {
    LOG(WARNING) << "StartConversionForRequest() failed";
    ResetState();
    return false;
  }

  segment_index_ = 0;
  state_ = CONVERSION;
  candidate_list_visible_ = false;
  UpdateCandidateList();
  InitializeSelectedCandidateIndices();
  return true;
}

bool SessionConverter::GetReadingText(const string &source_text,
                                      string *reading) {
  DCHECK(reading);
  reading->clear();
  Segments reverse_segments;
  if (!converter_->StartReverseConversion(&reverse_segments, source_text)) {
    return false;
  }
  if (reverse_segments.segments_size() == 0) {
    LOG(WARNING) << "no segments from reverse conversion";
    return false;
  }
  for (size_t i = 0; i < reverse_segments.segments_size(); ++i) {
    const mozc::Segment &segment = reverse_segments.segment(i);
    if (segment.candidates_size() == 0) {
      LOG(WARNING) << "got an empty segment from reverse conversion";
      return false;
    }
    reading->append(segment.candidate(0).value);
  }
  return true;
}

namespace {
Attributes GetT13nAttributes(const transliteration::TransliterationType type) {
  Attributes attributes = NO_ATTRIBUTES;
  switch (type) {
    case transliteration::HIRAGANA:  // "ひらがな"
      attributes = HIRAGANA;
      break;
    case transliteration::FULL_KATAKANA:  // "カタカナ"
      attributes = (FULL_WIDTH | KATAKANA);
      break;
    case transliteration::HALF_ASCII:  // "ascII"
      attributes = (HALF_WIDTH | ASCII);
      break;
    case transliteration::HALF_ASCII_UPPER:  // "ASCII"
      attributes = (HALF_WIDTH | ASCII | UPPER);
      break;
    case transliteration::HALF_ASCII_LOWER:  // "ascii"
      attributes = (HALF_WIDTH | ASCII | LOWER);
      break;
    case transliteration::HALF_ASCII_CAPITALIZED:  // "Ascii"
      attributes = (HALF_WIDTH | ASCII | CAPITALIZED);
      break;
    case transliteration::FULL_ASCII:  // "ａｓｃＩＩ"
      attributes = (FULL_WIDTH | ASCII);
      break;
    case transliteration::FULL_ASCII_UPPER:  // "ＡＳＣＩＩ"
      attributes = (FULL_WIDTH | ASCII | UPPER);
      break;
    case transliteration::FULL_ASCII_LOWER:  // "ａｓｃｉｉ"
      attributes = (FULL_WIDTH | ASCII | LOWER);
      break;
    case transliteration::FULL_ASCII_CAPITALIZED:  // "Ａｓｃｉｉ"
      attributes = (FULL_WIDTH | ASCII | CAPITALIZED);
      break;
    case transliteration::HALF_KATAKANA:  // "ｶﾀｶﾅ"
      attributes = (HALF_WIDTH | KATAKANA);
      break;
    default:
      LOG(ERROR) << "Unknown type: " << type;
      break;
  }
  return attributes;
}
}  // namespace

bool SessionConverter::ConvertToTransliteration(
    const composer::Composer &composer,
    const transliteration::TransliterationType type) {
  DCHECK(CheckState(COMPOSITION | SUGGESTION | PREDICTION | CONVERSION));
  if (CheckState(PREDICTION)) {
    // TODO(komatsu): A better way is to transliterate the key of the
    // focused candidate.  However it takes a long time.
    Cancel();
    DCHECK(CheckState(COMPOSITION));
  }

  Attributes query_attr =
      (GetT13nAttributes(type) &
       (HALF_WIDTH | FULL_WIDTH | ASCII | HIRAGANA | KATAKANA));

  if (CheckState(COMPOSITION | SUGGESTION)) {
    if (!Convert(composer)) {
      LOG(ERROR) << "Conversion failed";
      return false;
    }

    // TODO(komatsu): This is a workaround to transliterate the whole
    // preedit as a single segment.  We should modify
    // converter/converter.cc to enable to accept mozc::Segment::FIXED
    // from the session layer.
    if (segments_->conversion_segments_size() != 1) {
      string composition;
      GetPreedit(0, segments_->conversion_segments_size(), &composition);
      ResizeSegmentWidth(composer, Util::CharsLen(composition));
    }

    DCHECK(CheckState(CONVERSION));
    candidate_list_->MoveToAttributes(query_attr);
  } else {
    DCHECK(CheckState(CONVERSION));
    const Attributes current_attr =
        candidate_list_->GetDeepestFocusedCandidate().attributes();

    if ((query_attr & current_attr & ASCII) &&
        ((((query_attr & HALF_WIDTH) && (current_attr & FULL_WIDTH))) ||
         (((query_attr & FULL_WIDTH) && (current_attr & HALF_WIDTH))))) {
      query_attr |= (current_attr & (UPPER | LOWER | CAPITALIZED));
    }

    candidate_list_->MoveNextAttributes(query_attr);
  }
  candidate_list_visible_ = false;
  // Treat as top conversion candidate on usage stats.
  selected_candidate_indices_[segment_index_] = 0;
  SegmentFocus();
  return true;
}

bool SessionConverter::ConvertToHalfWidth(const composer::Composer &composer) {
  DCHECK(CheckState(COMPOSITION | SUGGESTION | PREDICTION | CONVERSION));
  if (CheckState(PREDICTION)) {
    // TODO(komatsu): A better way is to transliterate the key of the
    // focused candidate.  However it takes a long time.
    Cancel();
    DCHECK(CheckState(COMPOSITION));
  }

  string composition;
  if (CheckState(COMPOSITION | SUGGESTION)) {
    composer.GetStringForPreedit(&composition);
  } else {
    composition = GetSelectedCandidate(segment_index_).value;
  }

  // TODO(komatsu): make a function to return a logical sum of ScriptType.
  // If composition_ is "あｂｃ", it should be treated as Katakana.
  if (Util::ContainsScriptType(composition, Util::KATAKANA) ||
      Util::ContainsScriptType(composition, Util::HIRAGANA) ||
      Util::ContainsScriptType(composition, Util::KANJI) ||
      Util::IsKanaSymbolContained(composition)) {
    return ConvertToTransliteration(composer, transliteration::HALF_KATAKANA);
  } else {
    return ConvertToTransliteration(composer, transliteration::HALF_ASCII);
  }
}

bool SessionConverter::SwitchKanaType(const composer::Composer &composer) {
  DCHECK(CheckState(COMPOSITION | SUGGESTION | PREDICTION | CONVERSION));
  if (CheckState(PREDICTION)) {
    // TODO(komatsu): A better way is to transliterate the key of the
    // focused candidate.  However it takes a long time.
    Cancel();
    DCHECK(CheckState(COMPOSITION));
  }

  Attributes attributes = NO_ATTRIBUTES;
  if (CheckState(COMPOSITION | SUGGESTION)) {
    if (!Convert(composer)) {
      LOG(ERROR) << "Conversion failed";
      return false;
    }

    // TODO(komatsu): This is a workaround to transliterate the whole
    // preedit as a single segment.  We should modify
    // converter/converter.cc to enable to accept mozc::Segment::FIXED
    // from the session layer.
    if (segments_->conversion_segments_size() != 1) {
      string composition;
      GetPreedit(0, segments_->conversion_segments_size(), &composition);
      const ConversionRequest conversion_request(&composer, request_);
      converter_->ResizeSegment(segments_.get(),
                                conversion_request,
                                0, Util::CharsLen(composition));
      UpdateCandidateList();
    }

    attributes = (FULL_WIDTH | KATAKANA);
  } else {
    const Attributes current_attributes =
        candidate_list_->GetDeepestFocusedCandidate().attributes();
    // "漢字" -> "かんじ" -> "カンジ" -> "ｶﾝｼﾞ" -> "かんじ" -> ...
    if (current_attributes & HIRAGANA) {
      attributes = (FULL_WIDTH | KATAKANA);
    } else if ((current_attributes & KATAKANA) &&
               (current_attributes & FULL_WIDTH)) {
      attributes = (HALF_WIDTH | KATAKANA);
    } else {
      attributes = HIRAGANA;
    }
  }

  DCHECK(CheckState(CONVERSION));
  candidate_list_->MoveNextAttributes(attributes);
  candidate_list_visible_ = false;
  // Treat as top conversion candidate on usage stats.
  selected_candidate_indices_[segment_index_] = 0;
  SegmentFocus();
  return true;
}

namespace {

// Prepend the candidates to the first conversion segment.
void PrependCandidates(const Segment &previous_segment,
                       const string &preedit,
                       Segments *segments) {
  DCHECK(segments);

  // TODO(taku) want to have a method in converter to make an empty segment
  if (segments->conversion_segments_size() == 0) {
    segments->clear_conversion_segments();
    Segment *segment = segments->add_segment();
    segment->Clear();
    segment->set_key(preedit);
  }

  DCHECK_EQ(1, segments->conversion_segments_size());
  Segment *segment = segments->mutable_conversion_segment(0);
  DCHECK(segment);

  const size_t cands_size = previous_segment.candidates_size();
  for (size_t i = 0; i < cands_size; ++i) {
    Segment::Candidate *candidate = segment->push_front_candidate();
    candidate->CopyFrom(previous_segment.candidate(cands_size - i - 1));
  }
  *(segment->mutable_meta_candidates()) = previous_segment.meta_candidates();
}
}  // namespace


bool SessionConverter::Suggest(const composer::Composer &composer) {
  return SuggestWithPreferences(composer, conversion_preferences_);
}

bool SessionConverter::SuggestWithPreferences(
    const composer::Composer &composer,
    const ConversionPreferences &preferences) {
  DCHECK(CheckState(COMPOSITION | SUGGESTION));
  candidate_list_visible_ = false;

  // Normalize the current state by resetting the previous state.
  ResetState();

  // If we are on a password field, suppress suggestion.
  if (!preferences.request_suggestion ||
      composer.GetInputFieldType() == commands::Context::PASSWORD) {
    return false;
  }

  // Initialize the segments for suggestion.
  SetConversionPreferences(preferences, segments_.get());

  ConversionRequest conversion_request(&composer, request_);
  const size_t cursor = composer.GetCursor();
  if (cursor == composer.GetLength() || cursor == 0 ||
      !request_->mixed_conversion()) {
    conversion_request.set_create_partial_candidates(
        request_->auto_partial_suggestion());
    conversion_request.set_use_actual_converter_for_realtime_conversion(
        FLAGS_use_actual_converter_for_realtime_conversion);
    if (!converter_->StartSuggestionForRequest(conversion_request,
                                               segments_.get())) {
      // TODO(komatsu): Because suggestion is a prefix search, once
      // StartSuggestion returns false, this GetSuggestion always
      // returns false.  Refactor it.
      VLOG(1) << "StartSuggestionForRequest() returns no suggestions.";
      // Clear segments and keep the context
      converter_->CancelConversion(segments_.get());
      return false;
    }
  } else {
    // create_partial_candidates is false because auto partial suggestion
    // should be activated only when the cursor is at the tail or head from
    // the view point of UX.
    // use_actual_converter_for_realtime_conversion is also false because of
    // implementation reason. If the flag is true, all the composition
    // characters will be used in the below process, which conflicts
    // with *partial* prediction.
    if (!converter_->StartPartialSuggestionForRequest(conversion_request,
                                                      segments_.get())) {
      VLOG(1) << "StartPartialSuggestionForRequest() returns no suggestions.";
      // Clear segments and keep the context
      converter_->CancelConversion(segments_.get());
      return false;
    }
  }
  DCHECK_EQ(1, segments_->conversion_segments_size());

  // Copy current suggestions so that we can merge
  // prediction/suggestions later
  previous_suggestions_.CopyFrom(segments_->conversion_segment(0));

  // TODO(komatsu): the next line can be deleted.
  segment_index_ = 0;
  state_ = SUGGESTION;
  UpdateCandidateList();
  candidate_list_visible_ = true;
  InitializeSelectedCandidateIndices();
  return true;
}


bool SessionConverter::Predict(const composer::Composer &composer) {
  return PredictWithPreferences(composer, conversion_preferences_);
}

bool SessionConverter::IsEmptySegment(const Segment &segment) const {
  return ((segment.candidates_size() == 0) &&
          (segment.meta_candidates_size() == 0));
}

bool SessionConverter::PredictWithPreferences(
    const composer::Composer &composer,
    const ConversionPreferences &preferences) {
  // TODO(komatsu): DCHECK should be
  // DCHECK(CheckState(COMPOSITION | SUGGESTION | PREDICTION));
  DCHECK(CheckState(COMPOSITION | SUGGESTION | CONVERSION | PREDICTION));
  ResetResult();

  // Initialize the segments for prediction
  segments_->set_request_type(Segments::PREDICTION);
  SetConversionPreferences(preferences, segments_.get());

  const bool predict_first =
      !CheckState(PREDICTION) && IsEmptySegment(previous_suggestions_);

  const bool predict_expand =
      (CheckState(PREDICTION) &&
       !IsEmptySegment(previous_suggestions_) &&
       candidate_list_->size() > 0 &&
       candidate_list_->focused() &&
       candidate_list_->focused_index() == candidate_list_->last_index());

  segments_->clear_conversion_segments();

  if (predict_expand || predict_first) {
    ConversionRequest conversion_request(&composer, request_);
    conversion_request.set_use_actual_converter_for_realtime_conversion(
        FLAGS_use_actual_converter_for_realtime_conversion);
    if (!converter_->StartPredictionForRequest(conversion_request,
                                               segments_.get())) {
      LOG(WARNING) << "StartPredictionForRequest() failed";

      // TODO(komatsu): Perform refactoring after checking the stability test.
      //
      // If predict_expand is true, it means we have prevous_suggestions_.
      // So we can use it as the result of this prediction.
      if (predict_first) {
        ResetState();
        return false;
      }
    }
  }

  // Merge suggestions and prediction
  string preedit;
  composer.GetQueryForPrediction(&preedit);
  PrependCandidates(previous_suggestions_, preedit, segments_.get());

  segment_index_ = 0;
  state_ = PREDICTION;
  UpdateCandidateList();
  candidate_list_visible_ = true;
  InitializeSelectedCandidateIndices();

  return true;
}

bool SessionConverter::ExpandSuggestion(const composer::Composer &composer) {
  return ExpandSuggestionWithPreferences(composer, conversion_preferences_);
}

bool SessionConverter::ExpandSuggestionWithPreferences(
    const composer::Composer &composer,
    const ConversionPreferences &preferences) {
  DCHECK(CheckState(COMPOSITION | SUGGESTION | PREDICTION));
  if (CheckState(COMPOSITION)) {
    // Client can send EXPAND_SUGGESTION command when on composition mode.
    // In such case we do nothing.
    VLOG(1) << "ExpandSuggestion does nothing on composition mode.";
    return false;
  }

  ResetResult();

  // Expand suggestion.
  // Current implementation is hacky.
  // We want prediction candidates,
  // but want to set candidates' category SUGGESTION.
  // TODO(matsuzakit or yamaguchi): Refactor following lines,
  //     after implemention of partial conversion.

  // Initialize the segments for prediction.
  SetConversionPreferences(preferences, segments_.get());

  string preedit;
  composer.GetQueryForPrediction(&preedit);

  // We do not need "segments_->clear_conversion_segments()".
  // Without this statement we can add additional candidates into
  // existing segments.

  ConversionRequest conversion_request(&composer, request_);

  const size_t cursor = composer.GetCursor();
  if (cursor == composer.GetLength() || cursor == 0 ||
      !request_->mixed_conversion()) {
    conversion_request.set_create_partial_candidates(
        request_->auto_partial_suggestion());
    conversion_request.set_use_actual_converter_for_realtime_conversion(
        FLAGS_use_actual_converter_for_realtime_conversion);
    // This is abuse of StartPrediction().
    // TODO(matsuzakit or yamaguchi): Add ExpandSuggestion method
    //    to Converter class.
    if (!converter_->StartPredictionForRequest(conversion_request,
                                               segments_.get())) {
      LOG(WARNING) << "StartPredictionForRequest() failed";
    }
  } else {
    // c.f. SuggestWithPreferences for ConversionRequest flags.
    if (!converter_->StartPartialPredictionForRequest(conversion_request,
                                                      segments_.get())) {
      VLOG(1) << "StartPartialPredictionForRequest() returns no suggestions.";
      // Clear segments and keep the context
      converter_->CancelConversion(segments_.get());
      return false;
    }
  }
  // Overwrite the request type to SUGGESTION.
  // Without this logic, a candidate gets focused that is unexpected behavior.
  segments_->set_request_type(Segments::SUGGESTION);

  // Merge suggestions and predictions.
  PrependCandidates(previous_suggestions_, preedit, segments_.get());

  segment_index_ = 0;
  // Call AppendCandidateList instead of UpdateCandidateList because
  // we want to keep existing candidates.
  // As a result, ExpandSuggestionWithPreferences adds expanded suggestion
  // candidates at the tail of existing candidates.
  AppendCandidateList();
  candidate_list_visible_ = true;
  return true;
}

void SessionConverter::MaybeExpandPrediction(
    const composer::Composer &composer) {
  DCHECK(CheckState(PREDICTION | CONVERSION));

  // Expand the current suggestions and fill with Prediction results.
  if (!CheckState(PREDICTION) ||
      IsEmptySegment(previous_suggestions_) ||
      !candidate_list_->focused() ||
      candidate_list_->focused_index() != candidate_list_->last_index()) {
    return;
  }

  DCHECK(CheckState(PREDICTION));
  ResetResult();

  const size_t previous_index = candidate_list_->focused_index();
  if (!PredictWithPreferences(composer, conversion_preferences_)) {
    return;
  }

  DCHECK_LT(previous_index, candidate_list_->size());
  candidate_list_->MoveToId(candidate_list_->candidate(previous_index).id());
  UpdateSelectedCandidateIndex();
}

void SessionConverter::Cancel() {
  DCHECK(CheckState(PREDICTION | CONVERSION));
  ResetResult();

  // Clear segments and keep the context
  converter_->CancelConversion(segments_.get());
  ResetState();
}

void SessionConverter::Reset() {
  DCHECK(CheckState(COMPOSITION | SUGGESTION | PREDICTION | CONVERSION));

  // Even if composition mode, call ResetConversion
  // in order to clear history segments.
  converter_->ResetConversion(segments_.get());

  if (CheckState(COMPOSITION)) {
    return;
  }

  ResetResult();
  // Reset segments (and its internal context)
  ResetState();
}

void SessionConverter::Commit(const composer::Composer &composer,
                              const commands::Context &context) {
  DCHECK(CheckState(PREDICTION | CONVERSION));
  ResetResult();

  if (!UpdateResult(0, segments_->conversion_segments_size(), NULL)) {
    Cancel();
    ResetState();
    return;
  }

  for (size_t i = 0; i < segments_->conversion_segments_size(); ++i) {
    converter_->CommitSegmentValue(segments_.get(),
                                   i,
                                   GetCandidateIndexForConverter(i));
  }
  CommitUsageStats(state_, context);
  ConversionRequest conversion_request(&composer, request_);
  converter_->FinishConversion(conversion_request, segments_.get());
  ResetState();
}

bool SessionConverter::CommitSuggestionInternal(
    const composer::Composer &composer,
    const commands::Context &context,
    size_t *consumed_key_size) {
  DCHECK(consumed_key_size);
  DCHECK(CheckState(SUGGESTION));
  ResetResult();
  string preedit;
  composer.GetStringForPreedit(&preedit);

  if (!UpdateResult(0, segments_->conversion_segments_size(),
                    consumed_key_size)) {
    // Do not need to call Cancel like Commit because the current
    // state is SUGGESTION.
    ResetState();
    return false;
  }

  const size_t preedit_length = Util::CharsLen(preedit);

  // TODO(horo): When we will support hardware keyboard and introduce
  // shift+enter keymap in Android, this if condition may be insufficient.
  if (request_->zero_query_suggestion() &&
      *consumed_key_size < composer.GetLength()) {
    // A candidate was chosen from partial suggestion.
    converter_->CommitPartialSuggestionSegmentValue(
        segments_.get(),
        0,
        GetCandidateIndexForConverter(0),
        Util::SubString(preedit, 0, *consumed_key_size),
        Util::SubString(preedit,
                        *consumed_key_size,
                        preedit_length - *consumed_key_size));
    CommitUsageStats(SessionConverterInterface::SUGGESTION, context);
    InitializeSelectedCandidateIndices();
    // One or more segments must exist because new segment is inserted
    // just after the commited segment.
    DCHECK_GT(segments_->conversion_segments_size(), 0);
  } else {
    // Not partial suggestion so let's reset the state.
    converter_->CommitSegmentValue(segments_.get(),
                                   0,
                                   GetCandidateIndexForConverter(0));
    CommitUsageStats(SessionConverterInterface::SUGGESTION, context);
    ConversionRequest conversion_request(&composer, request_);
    converter_->FinishConversion(conversion_request, segments_.get());
    DCHECK_EQ(0, segments_->conversion_segments_size());
    ResetState();
  }
  return true;
}

bool SessionConverter::CommitSuggestionByIndex(
    const size_t index,
    const composer::Composer &composer,
    const commands::Context &context,
    size_t *consumed_key_size) {
  DCHECK(CheckState(SUGGESTION));
  if (index >= candidate_list_->size()) {
    LOG(ERROR) << "index is out of the range: " << index;
    return false;
  }
  candidate_list_->MoveToPageIndex(index);
  UpdateSelectedCandidateIndex();
  return CommitSuggestionInternal(composer, context, consumed_key_size);
}

bool SessionConverter::CommitSuggestionById(
    const int id,
    const composer::Composer &composer,
    const commands::Context &context,
    size_t *consumed_key_size) {
  DCHECK(CheckState(SUGGESTION));
  if (!candidate_list_->MoveToId(id)) {
    // Don't use CandidateMoveToId() method, which overwrites candidates.
    // This is harmful for EXPAND_SUGGESTION session command.
    LOG(ERROR) << "No id found";
    return false;
  }
  UpdateSelectedCandidateIndex();
  return CommitSuggestionInternal(composer, context, consumed_key_size);
}

void SessionConverter::CommitHeadToFocusedSegments(
    const composer::Composer &composer,
    const commands::Context &context,
    size_t *consumed_key_size) {
  CommitSegmentsInternal(
      composer, context, segment_index_ + 1, consumed_key_size);
}

void SessionConverter::CommitFirstSegment(
    const composer::Composer &composer,
    const commands::Context &context,
    size_t *consumed_key_size) {
  CommitSegmentsInternal(composer, context, 1, consumed_key_size);
}

void SessionConverter::CommitSegmentsInternal(
    const composer::Composer &composer,
    const commands::Context &context,
    size_t segments_to_commit,
    size_t *consumed_key_size) {
  DCHECK(CheckState(PREDICTION | CONVERSION));
  DCHECK(segments_->conversion_segments_size() >= segments_to_commit);
  ResetResult();
  candidate_list_visible_ = false;
  *consumed_key_size = 0;

  // If the number of segments is one, just call Commit.
  if (segments_->conversion_segments_size() == segments_to_commit) {
    Commit(composer, context);
    return;
  }

  // Store the first conversion segment to the result.
  if (!UpdateResult(0, segments_to_commit, NULL)) {
    // If the selected candidate of the first segment has the command
    // attribute, Cancel is performed instead of Commit.
    Cancel();
    ResetState();
    return;
  }

  vector<size_t> candidate_ids;
  for (size_t i = 0; i < segments_to_commit; ++i) {
    // Get the i-th (0 origin) conversion segment and the selected candidate.
    Segment *segment = segments_->mutable_conversion_segment(i);
    if (segment == NULL) {
      LOG(ERROR) << "There is no segment on position " << i;
      return;
    }

    // Accumulate the size of i-th segment's key.
    // The caller will remove corresponding characters from the composer.
    *consumed_key_size += Util::CharsLen(segment->key());

    // Collect candidate's id for each segment.
    candidate_ids.push_back(GetCandidateIndexForConverter(i));
  }
  converter_->CommitSegments(segments_.get(), candidate_ids);

  // Commit the [0, segments_to_commit - 1] conversion segment.
  CommitUsageStatsWithSegmentsSize(state_, context, segments_to_commit);

  // Adjust the segment_index, since the [0, segment_to_commit - 1] segments
  // disappeared.
  // Note that segment_index_ is unsigned.
  segment_index_ = segment_index_ > segments_to_commit
      ? segment_index_ - segments_to_commit : 0;
  UpdateCandidateList();
}

void SessionConverter::CommitPreedit(const composer::Composer &composer,
                                     const commands::Context &context) {
  string key, preedit, normalized_preedit;
  composer.GetQueryForConversion(&key);
  composer.GetStringForSubmission(&preedit);
  TextNormalizer::NormalizePreeditText(preedit, &normalized_preedit);
  SessionOutput::FillPreeditResult(preedit, result_.get());

  ConverterUtil::InitSegmentsFromString(key, normalized_preedit,
                                        segments_.get());

  CommitUsageStats(SessionConverterInterface::COMPOSITION, context);
  ConversionRequest conversion_request(&composer, request_);
  converter_->FinishConversion(conversion_request, segments_.get());
  ResetState();
}

void SessionConverter::CommitHead(
    size_t count, const composer::Composer &composer,
    size_t *consumed_key_size) {
  string preedit;
  composer.GetStringForSubmission(&preedit);
  if (count > preedit.length()) {
    *consumed_key_size = preedit.length();
  } else {
    *consumed_key_size = count;
  }
  preedit = Util::SubString(preedit, 0, *consumed_key_size);
  string composition;
  TextNormalizer::NormalizePreeditText(preedit, &composition);
  SessionOutput::FillPreeditResult(composition, result_.get());
}

void SessionConverter::Revert() {
  converter_->RevertConversion(segments_.get());
}

void SessionConverter::SegmentFocusInternal(size_t index) {
  DCHECK(CheckState(PREDICTION | CONVERSION));
  candidate_list_visible_ = false;
  if (CheckState(PREDICTION)) {
    return;  // Do nothing.
  }
  ResetResult();

  if (segment_index_ == index) {
    return;
  }

  SegmentFix();
  segment_index_ = index;
  UpdateCandidateList();
}

void SessionConverter::SegmentFocusRight() {
  if (segment_index_ + 1 >= segments_->conversion_segments_size()) {
    // If |segment_index_| is at the tail of the segments,
    // focus on the head.
    SegmentFocusLeftEdge();
  } else {
    SegmentFocusInternal(segment_index_ + 1);
  }
}

void SessionConverter::SegmentFocusLast() {
  const size_t r_edge = segments_->conversion_segments_size() - 1;
  SegmentFocusInternal(r_edge);
}

void SessionConverter::SegmentFocusLeft() {
  if (segment_index_ <= 0) {
    // If |segment_index_| is at the head of the segments,
    // focus on the tail.
    SegmentFocusLast();
  } else {
    SegmentFocusInternal(segment_index_ - 1);
  }
}

void SessionConverter::SegmentFocusLeftEdge() {
  SegmentFocusInternal(0);
}

void SessionConverter::ResizeSegmentWidth(const composer::Composer &composer,
                                          int delta) {
  DCHECK(CheckState(PREDICTION | CONVERSION));
  candidate_list_visible_ = false;
  if (CheckState(PREDICTION)) {
    return;  // Do nothing.
  }
  ResetResult();

  const ConversionRequest conversion_request(&composer, request_);
  if (!converter_->ResizeSegment(segments_.get(),
                                 conversion_request,
                                 segment_index_, delta)) {
    return;
  }

  UpdateCandidateList();
  // Clears selected index of a focused segment and trailing segments.
  // TODO(hsumita): Keep the indices if the segment type is FIXED_VALUE.
  selected_candidate_indices_.resize(segments_->conversion_segments_size());
  fill(selected_candidate_indices_.begin() + segment_index_ + 1,
       selected_candidate_indices_.end(), 0);
  UpdateSelectedCandidateIndex();
}

void SessionConverter::SegmentWidthExpand(const composer::Composer &composer) {
  ResizeSegmentWidth(composer, 1);
}

void SessionConverter::SegmentWidthShrink(const composer::Composer &composer) {
  ResizeSegmentWidth(composer, -1);
}

const Segment::Candidate *
SessionConverter::GetSelectedCandidateOfFocusedSegment() const {
  if (!candidate_list_->focused()) {
    return NULL;
  }
  const Candidate &cand = candidate_list_->focused_candidate();
  const Segment &seg = segments_->conversion_segment(segment_index_);
  return &seg.candidate(cand.id());
}

void SessionConverter::CandidateNext(const composer::Composer &composer) {
  DCHECK(CheckState(PREDICTION | CONVERSION));
  ResetResult();

  MaybeExpandPrediction(composer);
  candidate_list_->MoveNext();
  candidate_list_visible_ = true;
  UpdateSelectedCandidateIndex();
  SegmentFocus();
}

void SessionConverter::CandidateNextPage() {
  DCHECK(CheckState(PREDICTION | CONVERSION));
  ResetResult();

  candidate_list_->MoveNextPage();
  candidate_list_visible_ = true;
  UpdateSelectedCandidateIndex();
  SegmentFocus();
}

void SessionConverter::CandidatePrev() {
  DCHECK(CheckState(PREDICTION | CONVERSION));
  ResetResult();

  candidate_list_->MovePrev();
  candidate_list_visible_ = true;
  UpdateSelectedCandidateIndex();
  SegmentFocus();
}

void SessionConverter::CandidatePrevPage() {
  DCHECK(CheckState(PREDICTION | CONVERSION));
  ResetResult();

  candidate_list_->MovePrevPage();
  candidate_list_visible_ = true;
  UpdateSelectedCandidateIndex();
  SegmentFocus();
}

void SessionConverter::CandidateMoveToId(
    const int id, const composer::Composer &composer) {
  DCHECK(CheckState(SUGGESTION | PREDICTION | CONVERSION));
  ResetResult();

  if (CheckState(SUGGESTION)) {
    // This method makes a candidate focused but SUGGESTION state cannot
    // have focused candidate.
    // To solve this conflict we call Predict() method to transit to
    // PREDICTION state, on which existence of focused candidate is acceptable.
    Predict(composer);
  }
  DCHECK(CheckState(PREDICTION | CONVERSION));

  candidate_list_->MoveToId(id);
  candidate_list_visible_ = false;
  UpdateSelectedCandidateIndex();
  SegmentFocus();
}

void SessionConverter::CandidateMoveToPageIndex(const size_t index) {
  DCHECK(CheckState(PREDICTION | CONVERSION));
  ResetResult();

  candidate_list_->MoveToPageIndex(index);
  candidate_list_visible_ = false;
  UpdateSelectedCandidateIndex();
  SegmentFocus();
}

bool SessionConverter::CandidateMoveToShortcut(const char shortcut) {
  DCHECK(CheckState(PREDICTION | CONVERSION));

  if (!candidate_list_visible_) {
    VLOG(1) << "Candidate list is not displayed.";
    return false;
  }

  const string &shortcuts = operation_preferences_.candidate_shortcuts;
  if (shortcuts.empty()) {
    VLOG(1) << "No shortcuts";
    return false;
  }

  // Check if the input character is in the shortcut.
  // TODO(komatsu): Support non ASCII characters such as Unicode and
  // special keys.
  const string::size_type index = shortcuts.find(shortcut);
  if (index == string::npos) {
    VLOG(1) << "shortcut is not a member of shortcuts.";
    return false;
  }

  if (!candidate_list_->MoveToPageIndex(index)) {
    VLOG(1) << "shortcut is out of the range.";
    return false;
  }
  UpdateSelectedCandidateIndex();
  ResetResult();
  SegmentFocus();
  return true;
}

void SessionConverter::SetCandidateListVisible(bool visible) {
  candidate_list_visible_ = visible;
}

void SessionConverter::PopOutput(
    const composer::Composer &composer, commands::Output *output) {
  FillOutput(composer, output);
  ResetResult();
}

void SessionConverter::FillOutput(
    const composer::Composer &composer, commands::Output *output) const {
  if (output == NULL) {
    LOG(ERROR) << "output is NULL.";
    return;
  }
  if (result_->has_value()) {
    FillResult(output->mutable_result());
  }
  if (CheckState(COMPOSITION)) {
    if (!composer.Empty()) {
      session::SessionOutput::FillPreedit(composer,
                                          output->mutable_preedit());
    }
  }
  if (!IsActive()) {
    return;
  }

  // Composition on Suggestion
  if (CheckState(SUGGESTION)) {
    // When the suggestion comes from zero query suggestion, the
    // composer is empty.  In that case, preedit is not rendered.
    if (!composer.Empty()) {
      session::SessionOutput::FillPreedit(composer,
                                          output->mutable_preedit());
    }
  } else if (CheckState(PREDICTION | CONVERSION)) {
    // Conversion on Prediction or Conversion
    FillConversion(output->mutable_preedit());
  }
  // Candidate list
  if (CheckState(SUGGESTION | PREDICTION | CONVERSION) &&
      candidate_list_visible_) {
    FillCandidates(output->mutable_candidates());
  }
#ifndef __native_client__
  // All candidate words
  // In NaCl, we don't use the all candidate word data.
  if (CheckState(SUGGESTION | PREDICTION | CONVERSION)) {
    FillAllCandidateWords(output->mutable_all_candidate_words());
  }
#endif  // __native_client__
}

// static
void SessionConverter::SetConversionPreferences(
    const ConversionPreferences &preferences,
    Segments *segments) {
  segments->set_user_history_enabled(preferences.use_history);
  segments->set_max_history_segments_size(preferences.max_history_size);
}

SessionConverter* SessionConverter::Clone() const {
  SessionConverter *session_converter =
      new SessionConverter(converter_, request_);

  // Copy the members in order of their declarations.
  session_converter->state_ = state_;
  // TODO(team): copy of |converter_| member.
  // We cannot copy the member converter_ from SessionConverterInterface because
  // it doesn't (and shouldn't) define a method like GetConverter(). At the
  // moment it's ok because the current design guarantees that the converter is
  // singleton. However, we should refactor such bad design; see also the
  // comment right above.
  session_converter->segments_->CopyFrom(*segments_);
  session_converter->segment_index_ = segment_index_;
  session_converter->previous_suggestions_.CopyFrom(previous_suggestions_);
  session_converter->conversion_preferences_ = conversion_preferences();
  session_converter->operation_preferences_ = operation_preferences_;
  session_converter->result_->CopyFrom(*result_);

  if (session_converter->CheckState(SUGGESTION | PREDICTION | CONVERSION)) {
    session_converter->UpdateCandidateList();
    session_converter->candidate_list_->MoveToId(candidate_list_->focused_id());
    session_converter->SetCandidateListVisible(candidate_list_visible_);
  }

  session_converter->request_ = request_;
  session_converter->selected_candidate_indices_ = selected_candidate_indices_;

  return session_converter;
}

void SessionConverter::ResetResult() {
  result_->Clear();
}

void SessionConverter::ResetState() {
  state_ = COMPOSITION;
  segment_index_ = 0;
  previous_suggestions_.clear();
  candidate_list_visible_ = false;
  candidate_list_->Clear();
  selected_candidate_indices_.clear();
}

void SessionConverter::SegmentFocus() {
  DCHECK(CheckState(SUGGESTION | PREDICTION | CONVERSION));
  converter_->FocusSegmentValue(segments_.get(),
                                segment_index_,
                                GetCandidateIndexForConverter(segment_index_));
}

void SessionConverter::SegmentFix() {
  DCHECK(CheckState(SUGGESTION | PREDICTION | CONVERSION));
  converter_->CommitSegmentValue(segments_.get(),
                                 segment_index_,
                                 GetCandidateIndexForConverter(segment_index_));
}

void SessionConverter::GetPreedit(const size_t index,
                                  const size_t size,
                                  string *preedit) const {
  DCHECK(CheckState(SUGGESTION | PREDICTION | CONVERSION));
  DCHECK(index + size <= segments_->conversion_segments_size());
  DCHECK(preedit);

  preedit->clear();
  for (size_t i = index; i < size; ++i) {
    if (CheckState(CONVERSION)) {
      // In conversion mode, all the key of candidates is same.
      preedit->append(segments_->conversion_segment(i).key());
    } else {
      DCHECK(CheckState(SUGGESTION | PREDICTION));
      // In suggestion or prediction modes, each key may have
      // different keys, so content_key is used although it is
      // possibly dropped the conjugational word (ex. the content_key
      // of "はしる" is "はし").
      preedit->append(GetSelectedCandidate(i).content_key);
    }
  }
}

void SessionConverter::GetConversion(const size_t index,
                                     const size_t size,
                                     string *conversion) const {
  DCHECK(CheckState(SUGGESTION | PREDICTION | CONVERSION));
  DCHECK(index + size <= segments_->conversion_segments_size());
  DCHECK(conversion);

  conversion->clear();
  for (size_t i = index; i < size; ++i) {
    conversion->append(GetSelectedCandidateValue(i));
  }
}

size_t SessionConverter::GetConsumedPreeditSize(const size_t index,
                                                const size_t size) const {
  DCHECK(CheckState(SUGGESTION | PREDICTION | CONVERSION));
  DCHECK(index + size <= segments_->conversion_segments_size());

  if (CheckState(SUGGESTION | PREDICTION)) {
    DCHECK_EQ(1, size);
    const Segment &segment = segments_->conversion_segment(0);
    const int id = GetCandidateIndexForConverter(0);
    const Segment::Candidate &candidate = segment.candidate(id);
    return (candidate.attributes & Segment::Candidate::PARTIALLY_KEY_CONSUMED)
               ? candidate.consumed_key_size : kConsumedAllCharacters;
  }

  DCHECK(CheckState(CONVERSION));
  size_t result = 0;
  for (size_t i = index; i < size; ++i) {
    const int id = GetCandidateIndexForConverter(i);
    const Segment::Candidate &candidate =
        segments_->conversion_segment(i).candidate(id);
    DCHECK(!(candidate.attributes &
             Segment::Candidate::PARTIALLY_KEY_CONSUMED));
    result += Util::CharsLen(segments_->conversion_segment(i).key());
  }
  return result;
}

bool SessionConverter::MaybePerformCommandCandidate(
    const size_t index,
    const size_t size) const {
  // If a candidate has the command attribute, Cancel is performed
  // instead of Commit after executing the specified action.
  for (size_t i = index; i < size; ++i) {
    const int id = GetCandidateIndexForConverter(i);
    const Segment::Candidate &candidate =
        segments_->conversion_segment(i).candidate(id);
    if (candidate.attributes & Segment::Candidate::COMMAND_CANDIDATE) {
      switch (candidate.command) {
        case Segment::Candidate::DEFAULT_COMMAND:
          // Do nothing
          break;
        case Segment::Candidate::ENABLE_INCOGNITO_MODE:
          SetIncognitoMode(true);
          break;
        case Segment::Candidate::DISABLE_INCOGNITO_MODE:
          SetIncognitoMode(false);
          break;
        case Segment::Candidate::ENABLE_PRESENTATION_MODE:
          SetPresentationMode(true);
          break;
        case Segment::Candidate::DISABLE_PRESENTATION_MODE:
          SetPresentationMode(false);
          break;
        default:
          LOG(WARNING) << "Unknown command: " << candidate.command;
          break;
      }
      return true;
    }
  }
  return false;
}

bool SessionConverter::UpdateResult(size_t index, size_t size,
                                    size_t *consumed_key_size) {
  DCHECK(CheckState(SUGGESTION | PREDICTION | CONVERSION));

  // If command candidate is performed, result is not updated and
  // returns false.
  if (MaybePerformCommandCandidate(index, size)) {
    return false;
  }

  string preedit, conversion;
  GetPreedit(index, size, &preedit);
  GetConversion(index, size, &conversion);
  if (consumed_key_size) {
    *consumed_key_size = GetConsumedPreeditSize(index, size);
  }
  SessionOutput::FillConversionResult(preedit, conversion, result_.get());
  return true;
}

namespace {
// Convert transliteration::TransliterationType to id used in the
// converter.  The id number are negative values, and 0 of
// transliteration::TransliterationType is bound for -1 of the id.
int GetT13nId(const transliteration::TransliterationType type) {
  return -(type + 1);
}
}  // namespace

void SessionConverter::AppendCandidateList() {
  DCHECK(CheckState(SUGGESTION | PREDICTION | CONVERSION));

  // Meta candidates are added iff |candidate_list_| is empty.
  // This is because if |candidate_list_| is not empty we cannot decide
  // where to add meta candidates, especially use_cascading_window flag
  // is true (If there are two or more sub candidate lists, and existent
  // meta candidates are not located in the same list (distributed over
  // some lists), the most appropriate location to be added new meta candidates
  // cannot be decided).
  const bool add_meta_candidates = (candidate_list_->size() == 0);

  const Segment &segment = segments_->conversion_segment(segment_index_);
  for (size_t i = candidate_list_->next_available_id();
       i < segment.candidates_size();
       ++i) {
    candidate_list_->AddCandidate(i, segment.candidate(i).value);
    // if candidate has spelling correction attribute,
    // always display the candidate to let user know the
    // miss spelled candidate.
    if (i < 10 &&
        (segment.candidate(i).attributes &
         Segment::Candidate::SPELLING_CORRECTION)) {
      candidate_list_visible_ = true;
    }
  }

  const bool focused = (
      segments_->request_type() != Segments::SUGGESTION &&
      segments_->request_type() != Segments::PARTIAL_SUGGESTION &&
      segments_->request_type() != Segments::PARTIAL_PREDICTION);
  candidate_list_->set_focused(focused);

  if (segment.meta_candidates_size() == 0) {
    // For suggestion mode, it is natural that T13N is not initialized.
    if (CheckState(SUGGESTION)) {
      return;
    }
    // For other modes, records |segment| just in case.
    VLOG(1) << "T13N is not initialized: " << segment.key();
    return;
  }

  if (!add_meta_candidates) {
    return;
  }

  // Set transliteration candidates
  CandidateList *transliterations;
  if (operation_preferences_.use_cascading_window) {
    const bool kNoRotate = false;
    transliterations = candidate_list_->AllocateSubCandidateList(kNoRotate);
    transliterations->set_focused(true);

    const char kT13nLabel[] =
      // "そのほかの文字種";
      "\xe3\x81\x9d\xe3\x81\xae\xe3\x81\xbb\xe3\x81\x8b\xe3\x81\xae"
      "\xe6\x96\x87\xe5\xad\x97\xe7\xa8\xae";
    transliterations->set_name(kT13nLabel);
  } else {
    transliterations = candidate_list_.get();
  }

  // Add transliterations.
  for (size_t i = 0; i < transliteration::NUM_T13N_TYPES; ++i) {
    const transliteration::TransliterationType type =
      transliteration::TransliterationTypeArray[i];
    transliterations->AddCandidateWithAttributes(
        GetT13nId(type),
        segment.meta_candidate(i).value,
        GetT13nAttributes(type));
  }
}

void SessionConverter::UpdateCandidateList() {
  DCHECK(CheckState(SUGGESTION | PREDICTION | CONVERSION));
  candidate_list_->Clear();
  AppendCandidateList();
}

int SessionConverter::GetCandidateIndexForConverter(
    const size_t segment_index) const {
  DCHECK(CheckState(SUGGESTION | PREDICTION | CONVERSION));
  // If segment_index does not point to the focused segment, the value
  // should be always zero.
  if (segment_index != segment_index_) {
    return 0;
  }
  return candidate_list_->focused_id();
}

string SessionConverter::GetSelectedCandidateValue(
    const size_t segment_index) const {
  DCHECK(CheckState(SUGGESTION | PREDICTION | CONVERSION));
  const int id = GetCandidateIndexForConverter(segment_index);
  const Segment::Candidate &candidate =
      segments_->conversion_segment(segment_index).candidate(id);
  if (candidate.attributes & Segment::Candidate::COMMAND_CANDIDATE) {
    // Return an empty string, however this path should not be reached.
    return "";
  }
  return candidate.value;
}

const Segment::Candidate &SessionConverter::GetSelectedCandidate(
    const size_t segment_index) const {
  DCHECK(CheckState(SUGGESTION | PREDICTION | CONVERSION));
  const int id = GetCandidateIndexForConverter(segment_index);
  return segments_->conversion_segment(segment_index).candidate(id);
}

void SessionConverter::FillConversion(commands::Preedit *preedit) const {
  DCHECK(CheckState(PREDICTION | CONVERSION));
  SessionOutput::FillConversion(*segments_,
                                segment_index_,
                                candidate_list_->focused_id(),
                                preedit);
}

void SessionConverter::FillResult(commands::Result *result) const {
  result->CopyFrom(*result_);
}

void SessionConverter::FillCandidates(commands::Candidates *candidates) const {
  DCHECK(CheckState(SUGGESTION | PREDICTION | CONVERSION));
  if (!candidate_list_visible_) {
    return;
  }

  // The position to display the candidate window.
  size_t position = 0;
  string conversion;
  for (size_t i = 0; i < segment_index_; ++i) {
    position += Util::CharsLen(GetSelectedCandidate(i).value);
  }

  // Temporarily added to see if this condition is really satisfied in the
  // real world or not.
#ifdef CHANNEL_DEV
  CHECK_LT(0, segments_->conversion_segments_size());
#endif  // CHANNEL_DEV
  const Segment &segment = segments_->conversion_segment(segment_index_);
  SessionOutput::FillCandidates(
      segment, *candidate_list_, position, candidates);

  // Shortcut keys
  if (CheckState(PREDICTION | CONVERSION)) {
    SessionOutput::FillShortcuts(operation_preferences_.candidate_shortcuts,
                                 candidates);
  }

  // Store category
  switch (segments_->request_type()) {
    case Segments::CONVERSION:
      candidates->set_category(commands::CONVERSION);
      break;
    case Segments::PREDICTION:
      candidates->set_category(commands::PREDICTION);
      break;
    case Segments::SUGGESTION:
      candidates->set_category(commands::SUGGESTION);
      break;
    case Segments::PARTIAL_PREDICTION:
      // Not PREDICTION because we do not want to get focused candidate.
      candidates->set_category(commands::SUGGESTION);
      break;
    case Segments::PARTIAL_SUGGESTION:
      candidates->set_category(commands::SUGGESTION);
      break;
    default:
      LOG(WARNING) << "Unknown request type: " << segments_->request_type();
      candidates->set_category(commands::CONVERSION);
      break;
  }

  if (candidates->has_usages()) {
    candidates->mutable_usages()->set_category(commands::USAGE);
  }
  if (candidates->has_subcandidates()) {
    // TODO(komatsu): Subcandidate is not always for transliterations.
    // The category of the subcandidates should be checked.
    candidates->mutable_subcandidates()->set_category(
        commands::TRANSLITERATION);
  }

  // Store display type
  candidates->set_display_type(commands::MAIN);
  if (candidates->has_usages()) {
    candidates->mutable_usages()->set_display_type(commands::CASCADE);
  }
  if (candidates->has_subcandidates()) {
    // TODO(komatsu): Subcandidate is not always for transliterations.
    // The category of the subcandidates should be checked.
    candidates->mutable_subcandidates()->set_display_type(commands::CASCADE);
  }

  // Store footer.
  SessionOutput::FillFooter(candidates->category(), candidates);
}


void SessionConverter::FillAllCandidateWords(
    commands::CandidateList *candidates) const {
  DCHECK(CheckState(SUGGESTION | PREDICTION | CONVERSION));
  commands::Category category;
  switch (segments_->request_type()) {
    case Segments::CONVERSION:
      category = commands::CONVERSION;
      break;
    case Segments::PREDICTION:
      category = commands::PREDICTION;
      break;
    case Segments::SUGGESTION:
      category = commands::SUGGESTION;
      break;
    case Segments::PARTIAL_PREDICTION:
      // Not PREDICTION because we do not want to get focused candidate.
      category = commands::SUGGESTION;
      break;
    case Segments::PARTIAL_SUGGESTION:
      category = commands::SUGGESTION;
      break;
    default:
      LOG(WARNING) << "Unknown request type: " << segments_->request_type();
      category = commands::CONVERSION;
      break;
  }

  const Segment &segment = segments_->conversion_segment(segment_index_);
  SessionOutput::FillAllCandidateWords(
      segment, *candidate_list_, category, candidates);
}

void SessionConverter::SetRequest(const commands::Request *request) {
  request_ = request;
  candidate_list_->set_page_size(request->candidate_page_size());
}

void SessionConverter::OnStartComposition(const commands::Context &context) {
  bool revision_changed = false;
  if (context.has_revision()) {
    revision_changed = (context.revision() != client_revision_);
    client_revision_ = context.revision();
  }
  if (!context.has_preceding_text()) {
    // In this case, reset history segments when the revision is mismatched.
    if (revision_changed) {
      converter_->ResetConversion(segments_.get());
    }
    return;
  }

  const string &preceding_text = context.preceding_text();
  // If preceding text is empty, it is OK to reset the history segments by
  // calling ResetConversion.
  if (preceding_text.empty()) {
    converter_->ResetConversion(segments_.get());
    return;
  }

  // Hereafter, we keep the existing history segments as long as it is
  // consistent with the preceding text even when revision_changed is true.
  string history_text;
  for (size_t i = 0; i < segments_->segments_size(); ++i) {
    const Segment &segment = segments_->segment(i);
    if (segment.segment_type() != Segment::HISTORY) {
      break;
    }
    if (segment.candidates_size() == 0) {
      break;
    }
    history_text.append(segment.candidate(0).value);
  }

  if (!history_text.empty()) {
    // Compare |preceding_text| with |history_text| to check if the history
    // segments are still valid or not.
    DCHECK(!preceding_text.empty());
    DCHECK(!history_text.empty());
    if (preceding_text.size() > history_text.size()) {
      if (Util::EndsWith(preceding_text, history_text)) {
        // History segments seem to be consistent with preceding text.
        return;
      }
    } else {
      if (Util::EndsWith(history_text, preceding_text)) {
        // History segments seem to be consistent with preceding text.
        return;
      }
    }
  }

  // Here we reconstruct history segments from |preceding_text| regardless
  // of revision mismatch. If it fails the history segments is cleared anyway.
  converter_->ReconstructHistory(segments_.get(), preceding_text);
}

void SessionConverter::UpdateSelectedCandidateIndex() {
  int index;
  const Candidate &focused_candidate = candidate_list_->focused_candidate();
  if (focused_candidate.IsSubcandidateList()) {
    const int t13n_index =
        focused_candidate.subcandidate_list().focused_index();
    index = -1 - t13n_index;
  } else {
    // TODO(hsumita): Use id instead of focused index.
    index = candidate_list_->focused_index();
  }
  selected_candidate_indices_[segment_index_] = index;
}

void SessionConverter::InitializeSelectedCandidateIndices() {
  selected_candidate_indices_.clear();
  selected_candidate_indices_.resize(segments_->conversion_segments_size());
}

void SessionConverter::UpdateCandidateStats(const string &base_name,
                                            int32 index) {
  string prefix;
  if (index < 0) {
    prefix = "TransliterationCandidates";
    index = -1 - index;
  } else {
    prefix = base_name + "Candidates";
  }

  if (index <= 9) {
    const string stats_name = prefix + NumberUtil::SimpleItoa(index);
    UsageStats::IncrementCount(stats_name);
  } else {
    const string stats_name = prefix + "GE10";
    UsageStats::IncrementCount(stats_name);
  }
}

void SessionConverter::CommitUsageStats(
    SessionConverterInterface::State commit_state,
    const commands::Context &context) {
  size_t commit_segment_size = 0;
  switch (commit_state) {
    case COMPOSITION:
      commit_segment_size = 0;
      break;
    case SUGGESTION:
    case PREDICTION:
      commit_segment_size = 1;
      break;
    case CONVERSION:
      commit_segment_size = segments_->conversion_segments_size();
      break;
    default:
      LOG(DFATAL) << "Unexpected state: " << commit_state;
  }
  CommitUsageStatsWithSegmentsSize(commit_state, context, commit_segment_size);
}

void SessionConverter::CommitUsageStatsWithSegmentsSize(
    SessionConverterInterface::State commit_state,
    const commands::Context &context,
    size_t commit_segments_size) {
  CHECK_LE(commit_segments_size, selected_candidate_indices_.size());

  string stats_str;
  switch (commit_state) {
    case COMPOSITION:
      stats_str = "Composition";
      break;
    case SUGGESTION:
    case PREDICTION:
      // Suggestion related usage stats are collected as Prediction.
      stats_str = "Prediction";
      UpdateCandidateStats(stats_str, selected_candidate_indices_[0]);
      break;
    case CONVERSION:
      stats_str = "Conversion";
      for (size_t i = 0; i < commit_segments_size; ++i) {
        UpdateCandidateStats(stats_str,
                             selected_candidate_indices_[i]);
      }
      break;
    default:
      LOG(DFATAL) << "Unexpected state: " << commit_state;
      stats_str = "Unknown";
  }

  UsageStats::IncrementCount("Commit");
  UsageStats::IncrementCount("CommitFrom" + stats_str);

  if (stats_str != "Unknown") {
    if (SessionUsageStatsUtil::HasExperimentalFeature(context,
                                                      "chrome_omnibox")) {
      UsageStats::IncrementCount("CommitFrom" + stats_str + "InChromeOmnibox");
    }
    if (SessionUsageStatsUtil::HasExperimentalFeature(context,
                                                      "google_search_box")) {
      UsageStats::IncrementCount(
          "CommitFrom" + stats_str + "InGoogleSearchBox");
    }
  }

  const vector<int>::iterator it = selected_candidate_indices_.begin();
  selected_candidate_indices_.erase(it, it + commit_segments_size);
}

}  // namespace session
}  // namespace mozc
