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

// Class functions to be used for output by the Session class.

#include "session/internal/session_output.h"

#include <algorithm>
#include <map>
#include <string>
#include <vector>

#include "base/logging.h"
#include "base/port.h"
#include "base/text_normalizer.h"
#include "base/util.h"
#include "base/version.h"
#include "composer/composer.h"
#include "converter/segments.h"
#include "session/internal/candidate_list.h"

namespace mozc {
namespace session {
namespace {

bool FillAnnotation(const Segment::Candidate &candidate_value,
                    commands::Annotation *annotation) {
  bool is_modified = false;
  if (!candidate_value.prefix.empty()) {
    annotation->set_prefix(candidate_value.prefix);
    is_modified = true;
  }
  if (!candidate_value.suffix.empty()) {
    annotation->set_suffix(candidate_value.suffix);
    is_modified = true;
  }
  if (!candidate_value.description.empty()) {
    annotation->set_description(candidate_value.description);
    is_modified = true;
  }
  if (candidate_value.attributes &
      Segment::Candidate::USER_HISTORY_PREDICTION) {
    annotation->set_deletable(true);
    is_modified = true;
  }
  return is_modified;
}

void FillAllCandidateWordsInternal(
    const Segment &segment,
    const CandidateList &candidate_list,
    const int focused_id,
    commands::CandidateList *candidate_list_proto) {
  for (size_t i = 0; i < candidate_list.size(); ++i) {
    const Candidate &candidate = candidate_list.candidate(i);
    if (candidate.IsSubcandidateList()) {
      FillAllCandidateWordsInternal(
          segment, candidate.subcandidate_list(), focused_id,
          candidate_list_proto);
      continue;
    }

    commands::CandidateWord *candidate_word_proto =
      candidate_list_proto->add_candidates();
    // id
    const int id = candidate.id();
    candidate_word_proto->set_id(id);

    // index
    const int index = candidate_list_proto->candidates_size() - 1;
    candidate_word_proto->set_index(index);

    // check focused id
    if (id == focused_id && candidate_list.focused()) {
      candidate_list_proto->set_focused_index(index);
    }

    const Segment::Candidate &segment_candidate = segment.candidate(id);
    // key
    if (segment.key() != segment_candidate.content_key) {
      candidate_word_proto->set_key(segment_candidate.content_key);
    }
    // value
    candidate_word_proto->set_value(segment_candidate.value);

    // annotations
    commands::Annotation annotation;
    if (FillAnnotation(segment_candidate, &annotation)) {
      candidate_word_proto->mutable_annotation()->CopyFrom(annotation);
    }
  }
}

}  // namespace

// static
void SessionOutput::FillCandidate(
    const Segment &segment,
    const Candidate &candidate,
    commands::Candidates_Candidate *candidate_proto) {
  if (candidate.IsSubcandidateList()) {
    candidate_proto->set_value(candidate.subcandidate_list().name());
    candidate_proto->set_id(candidate.subcandidate_list().focused_id());
    return;
  }

  const Segment::Candidate &candidate_value = segment.candidate(candidate.id());
  candidate_proto->set_value(candidate_value.value);

  candidate_proto->set_id(candidate.id());
  // Set annotations
  commands::Annotation annotation;
  if (FillAnnotation(candidate_value, &annotation)) {
    candidate_proto->mutable_annotation()->CopyFrom(annotation);
  }

  if (!candidate_value.usage_title.empty()) {
    candidate_proto->set_information_id(candidate_value.usage_id);
  }
}

// static
void SessionOutput::FillCandidates(const Segment &segment,
                                   const CandidateList &candidate_list,
                                   const size_t position,
                                   commands::Candidates *candidates_proto) {
  if (candidate_list.focused()) {
    candidates_proto->set_focused_index(candidate_list.focused_index());
  }
  candidates_proto->set_size(candidate_list.size());
  candidates_proto->set_page_size(candidate_list.page_size());
  candidates_proto->set_position(position);

  size_t c_begin = 0;
  size_t c_end = 0;
  candidate_list.GetPageRange(candidate_list.focused_index(),
                              &c_begin, &c_end);

  // Store candidates.
  for (size_t i = c_begin; i <= c_end; ++i) {
    commands::Candidates_Candidate *candidate_proto =
      candidates_proto->add_candidate();
    candidate_proto->set_index(i);
    FillCandidate(segment, candidate_list.candidate(i), candidate_proto);
  }

  // Store subcandidates.
  if (candidate_list.focused_candidate().IsSubcandidateList()) {
    FillCandidates(segment,
                   candidate_list.focused_candidate().subcandidate_list(),
                   candidate_list.focused_index(),
                   candidates_proto->mutable_subcandidates());
  }

  // Store usages.
  FillUsages(segment, candidate_list, candidates_proto);
}

// static
void SessionOutput::FillAllCandidateWords(
    const Segment &segment,
    const CandidateList &candidate_list,
    const commands::Category category,
    commands::CandidateList *candidate_list_proto) {
  candidate_list_proto->set_category(category);
  FillAllCandidateWordsInternal(
      segment, candidate_list, candidate_list.focused_id(),
      candidate_list_proto);
}



// static
bool SessionOutput::ShouldShowUsages(const Segment &segment,
                                     const CandidateList &cand_list) {
  // Check if the shown candidate have the usage data.
  size_t c_begin = 0;
  size_t c_end = 0;
  cand_list.GetPageRange(cand_list.focused_index(), &c_begin, &c_end);
  for (size_t i = c_begin; i <= c_end; ++i) {
    if (cand_list.candidate(i).IsSubcandidateList()) {
      continue;
    }
    const Segment::Candidate &candidate =
      segment.candidate(cand_list.candidate(i).id());
    if (candidate.usage_title.empty()) {
      continue;
    }
    return true;
  }
  return false;
}


// static
void SessionOutput::FillUsages(const Segment &segment,
                               const CandidateList &cand_list,
                               commands::Candidates *candidates_proto) {
  if (!ShouldShowUsages(segment, cand_list)) {
    return;
  }

  commands::InformationList *usages = candidates_proto->mutable_usages();

  size_t c_begin = 0;
  size_t c_end = 0;
  cand_list.GetPageRange(cand_list.focused_index(), &c_begin, &c_end);

  typedef pair<int32, commands::Information *> IndexInfoPair;
  map<int32, IndexInfoPair> usageid_information_map;
  // Store usages.
  for (size_t i = c_begin; i <= c_end; ++i) {
    if (cand_list.candidate(i).IsSubcandidateList()) {
      continue;
    }
    const Segment::Candidate &candidate =
      segment.candidate(cand_list.candidate(i).id());
    if (candidate.usage_title.empty()) {
      continue;
    }

    int index;
    commands::Information *info;
    map<int32, IndexInfoPair>::iterator info_itr =
      usageid_information_map.find(candidate.usage_id);

    if (info_itr == usageid_information_map.end()) {
      index = usages->information_size();
      info = usages->add_information();
      info->set_id(candidate.usage_id);
      info->set_title(candidate.usage_title);
      info->set_description(candidate.usage_description);
      info->add_candidate_id(cand_list.candidate(i).id());
      usageid_information_map.insert(
          make_pair(candidate.usage_id, make_pair(index, info)));
    } else {
      index = info_itr->second.first;
      info = info_itr->second.second;
      info->add_candidate_id(cand_list.candidate(i).id());
    }
    if (cand_list.candidate(i).id() == cand_list.focused_id()) {
      usages->set_focused_index(index);
    }
  }
}


// static
void SessionOutput::FillShortcuts(const string &shortcuts,
                                  commands::Candidates *candidates_proto) {
  const size_t num_loop = min(
      static_cast<size_t>(candidates_proto->candidate_size()),
      shortcuts.size());
  for (size_t i = 0; i < num_loop; ++i) {
    const string shortcut = shortcuts.substr(i, 1);
    candidates_proto->mutable_candidate(i)->mutable_annotation()->
      set_shortcut(shortcut);
  }
}

// static
void SessionOutput::FillSubLabel(commands::Footer *footer) {
  // Delete the label because sub_label will be drawn on the same
  // place for the label.
  footer->clear_label();

  // Append third number of the version to sub_label.
  const string version = Version::GetMozcVersion();
  vector<string> version_numbers;
  Util::SplitStringUsing(version, ".", &version_numbers);
  if (version_numbers.size() > 2) {
    string sub_label("build ");
    sub_label.append(version_numbers[2]);
    footer->set_sub_label(sub_label);
  } else {
    LOG(ERROR) << "Unkonwn version format: " << version;
  }
}

// static
bool SessionOutput::FillFooter(const commands::Category category,
                               commands::Candidates *candidates) {
  if (category != commands::SUGGESTION &&
      category != commands::PREDICTION &&
      category != commands::CONVERSION) {
    return false;
  }

  bool show_build_number = true;
  commands::Footer *footer = candidates->mutable_footer();
  if (category == commands::SUGGESTION) {
    // TODO(komatsu): Enable to localized the message.
    // "Tabキーで選択"
    const char kLabel[] = ("Tab\xE3\x82\xAD\xE3\x83\xBC\xE3\x81\xA7"
                           "\xE9\x81\xB8\xE6\x8A\x9E");
    // TODO(komatsu): Need to check if Tab is not changed to other key binding.
    footer->set_label(kLabel);
  } else {
    // category is commands::PREDICTION or commands::CONVERSION.
    footer->set_index_visible(true);
    footer->set_logo_visible(true);

    // If the selected candidate is a user prediction history, tell the user
    // that it can be removed by Ctrl-Delete.
    if (candidates->has_focused_index()) {
      for (size_t i = 0; i < candidates->candidate_size(); ++i) {
        const commands::Candidates::Candidate &cand = candidates->candidate(i);
        if (cand.index() != candidates->focused_index()) {
          continue;
        }
        if (cand.has_annotation() && cand.annotation().deletable()) {
          // TODO(noriyukit): Change the message depending on user's keymap.
#if defined(OS_MACOSX)
          // "control+fn+deleteで履歴から削除"
          const char kDeleteInstruction[] =
              "\x63\x6F\x6E\x74\x72\x6F\x6C\x2B\x66\x6E\x2B\x64\x65\x6C\x65"
              "\x74\x65\xE3\x81\xA7\xE5\xB1\xA5\xE6\xAD\xB4\xE3\x81\x8B\xE3"
              "\x82\x89\xE5\x89\x8A\xE9\x99\xA4";
#elif defined(__native_client__)
          // "ctrl+alt+backspaceで履歴から削除"
          const char kDeleteInstruction[] =
              "\x63\x74\x72\x6C\x2B\x61\x6C\x74\x2B\x62\x61\x63\x6B\x73\x70"
              "\x61\x63\x65\xE3\x81\xA7\xE5\xB1\xA5\xE6\xAD\xB4\xE3\x81\x8B"
              "\xE3\x82\x89\xE5\x89\x8A\xE9\x99\xA4";
#else  // !OS_MACOSX && !__native_client__
          // "Ctrl+Delで履歴から削除"
          const char kDeleteInstruction[] =
              "\x43\x74\x72\x6C\x2B\x44\x65\x6C\xE3\x81\xA7\xE5\xB1\xA5"
              "\xE6\xAD\xB4\xE3\x81\x8B\xE3\x82\x89\xE5\x89\x8A\xE9\x99\xA4";
#endif  // OS_MACOSX || __native_client__
          footer->set_label(kDeleteInstruction);
          show_build_number = false;
        }
        break;
      }
    }
  }

  // Show the build number on the footer label for debugging when the build
  // configuration is official dev channel.
  if (show_build_number) {
#if defined(CHANNEL_DEV) && defined(GOOGLE_JAPANESE_INPUT_BUILD)
    FillSubLabel(footer);
#endif  // CHANNEL_DEV && GOOGLE_JAPANESE_INPUT_BUILD
  }

  return true;
}

// static
bool SessionOutput::AddSegment(const string &key,
                               const string &value,
                               const uint32 segment_type_mask,
                               commands::Preedit *preedit) {
  // Key is always normalized as a preedit text.
  string normalized_key;
  TextNormalizer::NormalizePreeditText(key, &normalized_key);

  string normalized_value;
  if (segment_type_mask & PREEDIT) {
    TextNormalizer::NormalizePreeditText(value, &normalized_value);
  } else if (segment_type_mask & CONVERSION) {
    normalized_value = value;
  } else {
    LOG(WARNING) << "Unknown segment type" << segment_type_mask;
    normalized_value = value;
  }

  if (normalized_value.empty()) {
    return false;
  }

  commands::Preedit::Segment *segment = preedit->add_segment();
  segment->set_key(normalized_key);
  segment->set_value(normalized_value);
  segment->set_value_length(Util::CharsLen(normalized_value));
  segment->set_annotation(commands::Preedit::Segment::UNDERLINE);
  if ((segment_type_mask & CONVERSION) && (segment_type_mask & FOCUSED)) {
    segment->set_annotation(commands::Preedit::Segment::HIGHLIGHT);
  } else {
    segment->set_annotation(commands::Preedit::Segment::UNDERLINE);
  }
  return true;
}

// static
void SessionOutput::FillPreedit(const composer::Composer &composer,
                                commands::Preedit *preedit) {
  string output;
  composer.GetStringForPreedit(&output);

  const uint32 kBaseType = PREEDIT;
  AddSegment(output, output, kBaseType, preedit);
  preedit->set_cursor(static_cast<uint32>(composer.GetCursor()));
}

// static
void SessionOutput::FillConversion(const Segments &segments,
                                   const size_t segment_index,
                                   const int candidate_id,
                                   commands::Preedit *preedit) {
  const uint32 kBaseType = CONVERSION;
  // Cursor position in conversion state should be the end of the preedit.
  size_t cursor = 0;
  for (size_t i = 0; i < segments.conversion_segments_size(); ++i) {
    const Segment &segment = segments.conversion_segment(i);
    if (i == segment_index) {
      const string &value = segment.candidate(candidate_id).value;
      if (AddSegment(segment.key(), value, kBaseType | FOCUSED, preedit) &&
          (!preedit->has_highlighted_position())) {
        preedit->set_highlighted_position(cursor);
      }
      cursor += Util::CharsLen(value);
    } else {
      const string &value = segment.candidate(0).value;
      AddSegment(segment.key(), value, kBaseType, preedit);
      cursor += Util::CharsLen(value);
    }
  }
  preedit->set_cursor(cursor);
}

// static
void SessionOutput::FillConversionResultWithoutNormalization(
    const string &key,
    const string &result,
    commands::Result *result_proto) {
  result_proto->set_type(commands::Result::STRING);
  result_proto->set_key(key);
  result_proto->set_value(result);
}

// static
void SessionOutput::FillConversionResult(const string &key,
                                         const string &result,
                                         commands::Result *result_proto) {
  // Key should be normalized as a preedit text.
  string normalized_key;
  TextNormalizer::NormalizePreeditText(key, &normalized_key);

  // value is already normalized by converter.
  FillConversionResultWithoutNormalization(
      normalized_key, result, result_proto);
}

// static
void SessionOutput::FillPreeditResult(const string &preedit,
                                      commands::Result *result_proto) {
  string normalized_preedit;
  TextNormalizer::NormalizePreeditText(preedit, &normalized_preedit);

  FillConversionResultWithoutNormalization(
      normalized_preedit, normalized_preedit, result_proto);
}

}  // namespace session
}  // namespace mozc
