// 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 "renderer/unix/candidate_window.h"

#include <sstream>

#include "base/logging.h"
#include "base/util.h"
#include "client/client_interface.h"
#include "renderer/renderer_style_handler.h"
#include "renderer/table_layout.h"
#include "renderer/unix/cairo_factory_interface.h"
#include "renderer/unix/const.h"
#include "renderer/unix/draw_tool.h"
#include "renderer/unix/font_spec.h"
#include "renderer/unix/text_renderer.h"

namespace mozc {
namespace renderer {
namespace gtk {

namespace {
string GetIndexGuideString(const commands::Candidates &candidates) {
  if (!candidates.has_footer() || !candidates.footer().index_visible()) {
    return "";
  }

  const int focused_index = candidates.focused_index();
  const int total_items = candidates.size();

  stringstream footer_string;
  return Util::StringPrintf("%d/%d ", focused_index + 1, total_items);
}

int GetCandidateArrayIndexByCandidateIndex(
    const commands::Candidates &candidates,
    int candidate_index) {
  for (size_t i = 0; i < candidates.candidate_size(); ++i) {
    const commands::Candidates::Candidate &candidate =
        candidates.candidate(i);
    if (candidate.index() == candidate_index) {
      return i;
    }
  }
  return candidates.candidate_size();
}
}  // namespace

CandidateWindow::CandidateWindow(
    TableLayoutInterface *table_layout,
    TextRendererInterface *text_renderer,
    DrawToolInterface *draw_tool,
    GtkWrapperInterface *gtk,
    CairoFactoryInterface *cairo_factory)
    : GtkWindowBase(gtk),
      table_layout_(table_layout),
      text_renderer_(text_renderer),
      draw_tool_(draw_tool),
      cairo_factory_(cairo_factory) {
}

bool CandidateWindow::OnPaint(GtkWidget *widget, GdkEventExpose* event) {
  draw_tool_->Reset(cairo_factory_->CreateCairoInstance(
      GetCanvasWidget()->window));

  DrawBackground();
  DrawShortcutBackground();
  DrawSelectedRect();
  DrawCells();
  DrawInformationIcon();
  DrawVScrollBar();
  DrawFooter();
  DrawFrame();
  return true;
}

void CandidateWindow::DrawBackground() {
  const Rect window_rect(Point(0, 0), GetWindowSize());
  draw_tool_->FillRect(window_rect, kDefaultBackgroundColor);
}

void CandidateWindow::DrawShortcutBackground() {
  if (table_layout_->number_of_columns() <= 0) {
    return;
  }

  const Rect first_column_rect = table_layout_->GetColumnRect(0);
  const Rect first_row_rect = table_layout_->GetRowRect(0);
  if (first_column_rect.IsRectEmpty() || first_row_rect.IsRectEmpty()) {
    return;
  }

  const Rect shortcut_background_area(first_row_rect.origin,
                                      first_column_rect.size);
  draw_tool_->FillRect(shortcut_background_area, kShortcutBackgroundColor);
}

void CandidateWindow::DrawSelectedRect() {
  if (!candidates_.has_focused_index()) {
    return;
  }

  const int selected_row_index = GetCandidateArrayIndexByCandidateIndex(
      candidates_, candidates_.focused_index());

  DCHECK_GE(selected_row_index, 0);

  if (selected_row_index >= candidates_.candidate_size()) {
    LOG(ERROR) << "focused index is invalid" << candidates_.focused_index();
    return;
  }

  const Rect selected_rect = table_layout_->GetRowRect(selected_row_index);
  draw_tool_->FillRect(selected_rect, kSelectedRowBackgroundColor);
  draw_tool_->FrameRect(selected_rect, kSelectedRowFrameColor, 1.0);
}

void CandidateWindow::DrawCells() {
  for (size_t i = 0; i < candidates_.candidate_size(); ++i) {
    const commands::Candidates::Candidate &candidate
        = candidates_.candidate(i);
    string shortcut, value, description;

    GetDisplayString(candidate, &shortcut, &value, &description);

    if (!shortcut.empty()) {
      text_renderer_->RenderText(shortcut,
                                 table_layout_->GetCellRect(i, COLUMN_SHORTCUT),
                                 FontSpec::FONTSET_SHORTCUT);
    }

    if (!value.empty()) {
      text_renderer_->RenderText(
          value,
          table_layout_->GetCellRect(i, COLUMN_CANDIDATE),
          FontSpec::FONTSET_CANDIDATE);
    }

    if (!description.empty()) {
      text_renderer_->RenderText(
          description,
          table_layout_->GetCellRect(i, COLUMN_DESCRIPTION),
          FontSpec::FONTSET_DESCRIPTION);
    }
  }
}

void CandidateWindow::DrawInformationIcon() {
  for (size_t i = 0; i < candidates_.candidate_size(); ++i) {
    if (!candidates_.candidate(i).has_information_id()) {
      continue;
    }
    const Rect row_rect = table_layout_->GetRowRect(i);
    const Rect usage_information_indicator_rect(
        row_rect.origin.x + row_rect.size.width - 6,
        row_rect.origin.y + 2,
        4,
        row_rect.size.height - 4);

    draw_tool_->FillRect(usage_information_indicator_rect, kIndicatorColor);
    draw_tool_->FrameRect(usage_information_indicator_rect, kIndicatorColor, 1);
  }
}

void CandidateWindow::DrawVScrollBar() {
  // TODO(nona): implement this function
}

void CandidateWindow::DrawFooterSeparator(Rect *footer_content_area) {
  DCHECK(footer_content_area);
  const Point dest(footer_content_area->Right(), footer_content_area->Top());
  draw_tool_->DrawLine(footer_content_area->origin, dest, kFrameColor,
                       kFooterSeparatorHeight);
  // The remaining footer content area is the one after removal of above/below
  // separation line.
  footer_content_area->origin.y += kFooterSeparatorHeight;
  footer_content_area->size.height -= kFooterSeparatorHeight;
}

void CandidateWindow::DrawFooterIndex(Rect *footer_content_rect) {
  DCHECK(footer_content_rect);
  if (!candidates_.has_footer() ||
      !candidates_.footer().index_visible() ||
      !candidates_.has_focused_index()) {
    return;
  }

  const string index_guide_string = GetIndexGuideString(candidates_);
  const Size index_guide_size = text_renderer_->GetPixelSize(
      FontSpec::FONTSET_FOOTER_INDEX, index_guide_string);
  // Render as right-aligned.
  Rect index_rect(footer_content_rect->Right() - index_guide_size.width,
                  footer_content_rect->Top(),
                  index_guide_size.width,
                  footer_content_rect->Height());
  text_renderer_->RenderText(index_guide_string,
                             index_rect,
                             FontSpec::FONTSET_FOOTER_INDEX);
  footer_content_rect->size.width -= index_guide_size.width;
}

void CandidateWindow::DrawFooterLabel(const Rect &footer_content_rect) {
  if (footer_content_rect.IsRectEmpty()) {
    return;
  }
  if (candidates_.footer().has_label()) {
    text_renderer_->RenderText(candidates_.footer().label(),
                               footer_content_rect,
                               FontSpec::FONTSET_FOOTER_LABEL);
  } else if (candidates_.footer().has_sub_label()) {
    text_renderer_->RenderText(candidates_.footer().sub_label(),
                               footer_content_rect,
                               FontSpec::FONTSET_FOOTER_SUBLABEL);
  }
}

void CandidateWindow::DrawLogo(Rect *footer_content_rect) {
  DCHECK(footer_content_rect);
  // TODO(nona): Implement this.
  // The current implementation is just a padding area.
  if (candidates_.footer().logo_visible()) {
    // The 47 pixel is same as icon width to be rendered in future.
    footer_content_rect->size.width -= 47;
    footer_content_rect->origin.x += 47;
  }
}

void CandidateWindow::DrawFooter() {
  if (!candidates_.has_footer()) {
    return;
  }

  Rect footer_content_area = table_layout_->GetFooterRect();
  if (footer_content_area.IsRectEmpty()) {
    return;
  }

  DrawFooterSeparator(&footer_content_area);
  DrawLogo(&footer_content_area);
  DrawFooterIndex(&footer_content_area);
  DrawFooterLabel(footer_content_area);
}

void CandidateWindow::DrawFrame() {
  const Rect client_rect(Point(0, 0), table_layout_->GetTotalSize());
  draw_tool_->FrameRect(client_rect, kFrameColor, 1);
}

void CandidateWindow::Initialize() {
  text_renderer_->Initialize(GetCanvasWidget()->window);
}

void CandidateWindow::UpdateScrollBarSize() {
  // TODO(nona) : Implement this.
}

void CandidateWindow::UpdateFooterSize() {
  if (!candidates_.has_footer()) {
    return;
  }

  Size footer_size(0, 0);

  if (candidates_.footer().has_label()) {
    const Size label_string_size = text_renderer_->GetPixelSize(
        FontSpec::FONTSET_FOOTER_LABEL,
        candidates_.footer().label());
    footer_size.width += label_string_size.width;
    footer_size.height = max(footer_size.height, label_string_size.height);
  } else if (candidates_.footer().has_sub_label()) {
    const Size label_string_size = text_renderer_->GetPixelSize(
        FontSpec::FONTSET_FOOTER_LABEL,
        candidates_.footer().sub_label());
    footer_size.width += label_string_size.width;
    footer_size.height = max(footer_size.height, label_string_size.height);
  }

  if (candidates_.footer().index_visible()) {
    const Size index_guide_size = text_renderer_->GetPixelSize(
      FontSpec::FONTSET_FOOTER_INDEX,
      GetIndexGuideString(candidates_));
    footer_size.width += index_guide_size.width;
    footer_size.height = max(footer_size.height, index_guide_size.height);
  }

  if (candidates_.candidate_size() < candidates_.size()) {
    const Size minimum_size = text_renderer_->GetPixelSize(
      FontSpec::FONTSET_CANDIDATE,
      kMinimumCandidateAndDescriptionWidthAsString);
    table_layout_->EnsureColumnsWidth(
      COLUMN_CANDIDATE, COLUMN_DESCRIPTION, minimum_size.width);
  }

  if (candidates_.footer().logo_visible()) {
    // TODO(nona): Implement logo sizing.
    footer_size.width += 47;
  }
  footer_size.height += kFooterSeparatorHeight;

  table_layout_->EnsureFooterSize(footer_size);
}

void CandidateWindow::UpdateGap1Size() {
  const Size gap1_size =
      text_renderer_->GetPixelSize(FontSpec::FONTSET_CANDIDATE, " ");
  table_layout_->EnsureCellSize(COLUMN_GAP1, gap1_size);
}

void CandidateWindow::UpdateCandidatesSize(bool *has_description) {
  DCHECK(has_description);
  *has_description = false;
  for (size_t i = 0; i < candidates_.candidate_size(); ++i) {
    const commands::Candidates::Candidate &candidate =
        candidates_.candidate(i);

    string shortcut, description, candidate_string;
    GetDisplayString(candidate, &shortcut, &candidate_string, &description);

    if (!shortcut.empty()) {
      string text;
      text.push_back(' ');
      text.append(shortcut);
      text.push_back(' ');
      const Size rendering_size = text_renderer_->GetPixelSize(
          FontSpec::FONTSET_SHORTCUT, text);
      table_layout_->EnsureCellSize(COLUMN_SHORTCUT, rendering_size);
    }

    if (!candidate_string.empty()) {
      const Size rendering_size = text_renderer_->GetPixelSize(
          FontSpec::FONTSET_CANDIDATE, candidate_string);
      table_layout_->EnsureCellSize(COLUMN_CANDIDATE, rendering_size);
    }

    if (!description.empty()) {
      string text;
      text.append(description);
      text.push_back(' ');
      const Size rendering_size = text_renderer_->GetPixelSize(
          FontSpec::FONTSET_DESCRIPTION, text);
      table_layout_->EnsureCellSize(COLUMN_DESCRIPTION, rendering_size);
      *has_description = true;
    }
  }
}

void CandidateWindow::UpdateGap2Size(bool has_description) {
  const char *gap2_string = (has_description ? "   " : " ");
  const Size gap2_size = text_renderer_->GetPixelSize(
      FontSpec::FONTSET_CANDIDATE, gap2_string);
  table_layout_->EnsureCellSize(COLUMN_GAP2, gap2_size);
}

Size CandidateWindow::Update(const commands::Candidates &candidates) {
  DCHECK(
      (candidates_.category()  == commands::CONVERSION) ||
      (candidates_.category()  == commands::PREDICTION) ||
      (candidates_.category()  == commands::TRANSLITERATION) ||
      (candidates_.category()  == commands::SUGGESTION) ||
      (candidates_.category()  == commands::USAGE))
      << "Unknown candidate category" << candidates_.category();

  candidates_.CopyFrom(candidates);

  table_layout_->Initialize(candidates_.candidate_size(), NUMBER_OF_COLUMNS);
  table_layout_->SetWindowBorder(kWindowBorder);
  table_layout_->SetRowRectPadding(kRowRectPadding);

  UpdateScrollBarSize();
  UpdateFooterSize();
  UpdateGap1Size();
  bool has_description;
  UpdateCandidatesSize(&has_description);
  UpdateGap2Size(has_description);

  table_layout_->FreezeLayout();
  Resize(table_layout_->GetTotalSize());
  Redraw();
  return table_layout_->GetTotalSize();
}

void CandidateWindow::GetDisplayString(
    const commands::Candidates::Candidate &candidate,
    string *shortcut,
    string *value,
    string *description) {
  DCHECK(shortcut);
  DCHECK(value);
  DCHECK(description);

  shortcut->clear();
  value->clear();
  description->clear();

  if (!candidate.has_value()) {
    return;
  }
  value->assign(candidate.value());

  if (!candidate.has_annotation()) {
    return;
  }

  const commands::Annotation &annotation = candidate.annotation();

  if (annotation.has_shortcut()) {
    shortcut->assign(annotation.shortcut());
  }

  if (annotation.has_description()) {
    description->assign(annotation.description());
  }

  if (annotation.has_prefix()) {
    value->assign(annotation.prefix());
    value->append(candidate.value());
  }

  if (annotation.has_suffix()) {
    value->append(annotation.suffix());
  }
}

Rect CandidateWindow::GetCandidateColumnInClientCord() const {
  DCHECK(table_layout_->IsLayoutFrozen()) << "Table layout is not frozen.";
  return table_layout_->GetCellRect(0, COLUMN_CANDIDATE);
}

void CandidateWindow::OnMouseLeftUp(const Point &pos) {
  if (send_command_interface_ == NULL) {
    LOG(ERROR) << "send_command_interface_ is NULL";
    return;
  }

  const int kSelectedIdx = GetSelectedRowIndex(pos);
  if (kSelectedIdx == -1) {  // out of range
    return;
  }

  const commands::Candidates::Candidate &candidate =
      candidates_.candidate(kSelectedIdx);
  commands::SessionCommand command;
  command.set_type(commands::SessionCommand::SELECT_CANDIDATE);
  command.set_id(candidate.id());
  commands::Output output;
  send_command_interface_->SendCommand(command, &output);
  return;
}

int CandidateWindow::GetSelectedRowIndex(const Point &pos) const {
  for (size_t i = 0; i < candidates_.candidate_size(); ++i) {
    const Rect rect = table_layout_->GetRowRect(i);

    if (rect.PtrInRect(pos)) {
      return i;
    }
  }
  return -1;
}

bool CandidateWindow::SetSendCommandInterface(
    client::SendCommandInterface *send_command_interface) {
  send_command_interface_ = send_command_interface;
  return true;
}

void CandidateWindow::ReloadFontConfig(const string &font_description) {
  text_renderer_->ReloadFontConfig(font_description);
}

}  // namespace gtk
}  // namespace renderer
}  // namespace mozc
