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

#include "unix/ibus/ibus_candidate_window_handler.h"

#include <cstdio>
#include <cstdlib>

#include "base/logging.h"
#include "session/commands.pb.h"
#include "unix/ibus/mozc_engine_property.h"

namespace mozc {
namespace ibus {

namespace {

// Returns an IBusText used for showing the auxiliary text in the candidate
// window. Returns NULL if no text has to be shown. Caller must release the
// returned IBusText object.
IBusText *ComposeAuxiliaryText(const commands::Candidates &candidates) {
  if (!candidates.has_footer()) {
    // We don't have to show the auxiliary text.
    return NULL;
  }
  const commands::Footer &footer = candidates.footer();

  string auxiliary_text;
  if (footer.has_label()) {
    // TODO(yusukes,mozc-team): label() is not localized. Currently, it's always
    // written in Japanese (in UTF-8).
    auxiliary_text = footer.label();
  } else if (footer.has_sub_label()) {
    // Windows client shows sub_label() only when label() is not specified. We
    // follow the policy.
    auxiliary_text = footer.sub_label();
  }

  if (footer.has_index_visible() && footer.index_visible() &&
      candidates.has_focused_index()) {
    // Max size of candidates is 200 so 128 is sufficient size for the buffer.
    char index_buf[128] = {0};
    const int result = snprintf(index_buf,
                                sizeof(index_buf) - 1,
                                "%s%d/%d",
                                (auxiliary_text.empty() ? "" : " "),
                                candidates.focused_index() + 1,
                                candidates.size());
    DCHECK_GE(result, 0) << "snprintf in ComposeAuxiliaryText failed";
    auxiliary_text += index_buf;
  }
  return auxiliary_text.empty() ?
      NULL : ibus_text_new_from_string(auxiliary_text.c_str());
}
}  // namespace

IBusCandidateWindowHandler::IBusCandidateWindowHandler() {
}

IBusCandidateWindowHandler::~IBusCandidateWindowHandler() {
}

void IBusCandidateWindowHandler::Update(IBusEngine *engine,
                                        const commands::Output &output) {
  UpdateCandidates(engine, output);
  UpdateAuxiliaryText(engine, output);
}

void IBusCandidateWindowHandler::Hide(IBusEngine *engine) {
  ibus_engine_hide_lookup_table(engine);
  ibus_engine_hide_auxiliary_text(engine);
}

void IBusCandidateWindowHandler::Show(IBusEngine *engine) {
  ibus_engine_show_lookup_table(engine);
  ibus_engine_show_auxiliary_text(engine);
}

// TODO(hsumita): Writes test for this method.
bool IBusCandidateWindowHandler::UpdateCandidates(
    IBusEngine *engine,
    const commands::Output &output) {
  if (!output.has_candidates() || output.candidates().candidate_size() == 0) {
    ibus_engine_hide_lookup_table(engine);
    return true;
  }

  const gboolean kRound = TRUE;
  const commands::Candidates &candidates = output.candidates();
  const gboolean cursor_visible = candidates.has_focused_index() ?
      TRUE : FALSE;
  int cursor_pos = 0;
  if (candidates.has_focused_index()) {
    for (int i = 0; i < candidates.candidate_size(); ++i) {
      if (candidates.focused_index() == candidates.candidate(i).index()) {
        cursor_pos = i;
      }
    }
  }

  size_t page_size = kPageSize;
  if (candidates.has_category() &&
      candidates.category() == commands::SUGGESTION &&
      page_size > candidates.candidate_size()) {
    page_size = candidates.candidate_size();
  }
  IBusLookupTable *table = ibus_lookup_table_new(page_size,
                                                 cursor_pos,
                                                 cursor_visible,
                                                 kRound);
  if (candidates.direction() == commands::Candidates::VERTICAL) {
    ibus_lookup_table_set_orientation(table, IBUS_ORIENTATION_VERTICAL);
  } else {
    ibus_lookup_table_set_orientation(table, IBUS_ORIENTATION_HORIZONTAL);
  }

  for (int i = 0; i < candidates.candidate_size(); ++i) {
    const commands::Candidates::Candidate &candidate = candidates.candidate(i);
    IBusText *text = ibus_text_new_from_string(candidate.value().c_str());
    ibus_lookup_table_append_candidate(table, text);
    // |text| is released by ibus_engine_update_lookup_table along with |table|.

    const bool has_label = candidate.has_annotation() &&
        candidate.annotation().has_shortcut();
    // Need to append an empty string when the candidate does not have a
    // shortcut. Otherwise the ibus lookup table shows numeric labels.
    IBusText *label =
        ibus_text_new_from_string(has_label ?
                                  candidate.annotation().shortcut().c_str() :
                                  "");
    ibus_lookup_table_append_label(table, label);
    // |label| is released by ibus_engine_update_lookup_table along with
    // |table|.
  }

  ibus_engine_update_lookup_table(engine, table, TRUE);
  // |table| is released by ibus_engine_update_lookup_table.
  return true;
}

// TODO(hsumita): Writes test for this method.
bool IBusCandidateWindowHandler::UpdateAuxiliaryText(
    IBusEngine *engine,
    const commands::Output &output) {
  if (!output.has_candidates()) {
    ibus_engine_hide_auxiliary_text(engine);
    return true;
  }

  IBusText *auxiliary_text = ComposeAuxiliaryText(output.candidates());
  if (auxiliary_text) {
    ibus_engine_update_auxiliary_text(engine, auxiliary_text, TRUE);
    // |auxiliary_text| is released by ibus_engine_update_auxiliary_text.
  } else {
    ibus_engine_hide_auxiliary_text(engine);
  }

  return true;
}

void IBusCandidateWindowHandler::OnIBusCustomFontDescriptionChanged(
    const string &custom_font_description) {
  // Do nothing
  // The custom font description is managed by ibus directly.
}

void IBusCandidateWindowHandler::OnIBusUseCustomFontDescriptionChanged(
    bool use_custom_font_description) {
  // Do nothing
  // The custom font description is managed by ibus directly.
}

}  // namespace ibus
}  // namespace mozc
