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

#include <windows.h>

#include <sstream>

#include "base/coordinates.h"
#include "base/logging.h"
#include "base/util.h"
#include "client/client_interface.h"
#include "renderer/renderer_command.pb.h"
#include "renderer/renderer_style.pb.h"
#include "renderer/renderer_style_handler.h"
#include "renderer/table_layout.h"
#include "renderer/win32/text_renderer.h"
#include "renderer/win_resource.h"

namespace mozc {
namespace renderer {
namespace win32 {

using WTL::CBitmap;
using WTL::CDC;
using WTL::CDCHandle;
using WTL::CMemoryDC;
using WTL::CPaintDC;
using WTL::CPenHandle;
using WTL::CPoint;
using WTL::CRect;
using WTL::CSize;

using mozc::commands::Candidates;
using mozc::commands::Information;
using mozc::commands::InformationList;
using mozc::commands::Output;
using mozc::commands::SessionCommand;
using mozc::renderer::RendererStyle;
using mozc::renderer::RendererStyleHandler;

namespace {
const COLORREF kDefaultBackgroundColor = RGB(0xff, 0xff, 0xff);
const UINT_PTR kIdDelayShowHideTimer = 100;

bool SendUsageStatsEvent(client::SendCommandInterface *command_sender,
                         const SessionCommand::UsageStatsEvent &event) {
  if (command_sender == nullptr) {
    return false;
  }
  SessionCommand command;
  command.set_type(SessionCommand::USAGE_STATS_EVENT);
  command.set_usage_stats_event(event);
  VLOG(2) << "SendUsageStatsEvent " << command.DebugString();
  Output dummy_output;
  return command_sender->SendCommand(command, &dummy_output);
}
}  // namespace


// ------------------------------------------------------------------------
// InfolistWindow
// ------------------------------------------------------------------------

InfolistWindow::InfolistWindow()
    : candidates_(new commands::Candidates),
      metrics_changed_(false),
      text_renderer_(TextRenderer::Create()),
      style_(new RendererStyle),
      visible_(false),
      send_command_interface_(nullptr) {
  mozc::renderer::RendererStyleHandler::GetRendererStyle(style_.get());
}

InfolistWindow::~InfolistWindow() {}

void InfolistWindow::OnDestroy() {
  // PostQuitMessage may stop the message loop even though other
  // windows are not closed. WindowManager should close these windows
  // before process termination.
  ::PostQuitMessage(0);
}

BOOL InfolistWindow::OnEraseBkgnd(CDCHandle dc) {
  // We do not have to erase background
  // because all pixels in client area will be drawn in the DoPaint method.
  return TRUE;
}

void InfolistWindow::OnGetMinMaxInfo(MINMAXINFO *min_max_info) {
  // Do not restrict the window size in case the candidate window must be
  // very small size.
  min_max_info->ptMinTrackSize.x = 1;
  min_max_info->ptMinTrackSize.y = 1;
  SetMsgHandled(TRUE);
}

void InfolistWindow::OnPaint(CDCHandle dc) {
  CRect client_rect;
  this->GetClientRect(&client_rect);

  if (dc != nullptr) {
    CMemoryDC memdc(dc, client_rect);
    DoPaint(memdc.m_hDC);
  } else  {
    CPaintDC paint_dc(this->m_hWnd);
    { // Create a copy of |paint_dc| and render the candidate strings in it.
      // The image rendered to this |memdc| is to be copied into the original
      // |paint_dc| in its destructor. So, we don't have to explicitly call
      // any functions that copy this |memdc| to the |paint_dc| but putting
      // the following code into a local block.
      CMemoryDC memdc(paint_dc, client_rect);
      DoPaint(memdc.m_hDC);
    }
  }
}

void InfolistWindow::OnPrintClient(CDCHandle dc, UINT uFlags) {
  OnPaint(dc);
}

Size InfolistWindow::DoPaint(CDCHandle dc) {
  if (dc.m_hDC != nullptr) {
    dc.SetBkMode(TRANSPARENT);
  }
  const RendererStyle::InfolistStyle &infostyle = style_->infolist_style();
  const InformationList &usages = candidates_->usages();

  int ypos = infostyle.window_border();

  if ((dc.m_hDC != nullptr) && infostyle.has_caption_string()) {
    const RendererStyle::TextStyle &caption_style =
      infostyle.caption_style();
    const int caption_height = infostyle.caption_height();
    const Rect backgrounnd_rect(infostyle.window_border(), ypos,
      infostyle.window_width() - infostyle.window_border() * 2,
      caption_height);
    const CRect background_crect(
        backgrounnd_rect.Left(), backgrounnd_rect.Top(),
        backgrounnd_rect.Right(), backgrounnd_rect.Bottom());

    dc.FillSolidRect(&background_crect,
        RGB(infostyle.caption_background_color().r(),
            infostyle.caption_background_color().g(),
            infostyle.caption_background_color().b()));

    wstring caption_str;
    const Rect caption_rect(
      infostyle.window_border() + infostyle.caption_padding()
      + caption_style.left_padding(),
      ypos + infostyle.caption_padding(),
      infostyle.window_width() - infostyle.window_border() * 2,
      caption_height);
    mozc::Util::UTF8ToWide(infostyle.caption_string().c_str(),
                           &caption_str);

    text_renderer_->RenderText(dc,
                               caption_str,
                               caption_rect,
                               TextRenderer::FONTSET_INFOLIST_CAPTION);
  }
  ypos += infostyle.caption_height();

  for (int i = 0; i < usages.information_size(); ++i) {
    Size size = DoPaintRow(dc, i, ypos);
    ypos += size.height;
  }
  ypos += infostyle.window_border();

  if (dc.m_hDC != nullptr) {
    const CRect rect(0, 0, infostyle.window_width(), ypos);
    dc.SetDCBrushColor(
        RGB(infostyle.border_color().r(),
            infostyle.border_color().g(),
            infostyle.border_color().b()));
    dc.FrameRect(&rect,
                 static_cast<HBRUSH>(GetStockObject(DC_BRUSH)));
  }


  return Size(style_->infolist_style().window_width(), ypos);
}

Size InfolistWindow::DoPaintRow(CDCHandle dc, int row, int ypos) {
  const RendererStyle::InfolistStyle &infostyle = style_->infolist_style();
  const InformationList &usages = candidates_->usages();
  const RendererStyle::TextStyle &title_style = infostyle.title_style();
  const RendererStyle::TextStyle &desc_style = infostyle.description_style();
  const int title_width = infostyle.window_width() -
      title_style.left_padding() - title_style.right_padding() -
      infostyle.window_border() * 2 -
      infostyle.row_rect_padding() * 2;
  const int desc_width = infostyle.window_width() -
      desc_style.left_padding() - desc_style.right_padding() -
      infostyle.window_border() * 2 -
      infostyle.row_rect_padding() * 2;
  const Information &info = usages.information(row);

  wstring title_str;
  mozc::Util::UTF8ToWide(info.title().c_str(), &title_str);
  const Size title_size = text_renderer_->MeasureStringMultiLine(
      TextRenderer::FONTSET_INFOLIST_TITLE, title_str, title_width);

  wstring desc_str;
  mozc::Util::UTF8ToWide(info.description().c_str(), &desc_str);
  const Size desc_size = text_renderer_->MeasureStringMultiLine(
      TextRenderer::FONTSET_INFOLIST_DESCRIPTION, desc_str, desc_width);

  int row_height = title_size.height + desc_size.height +
                   infostyle.row_rect_padding() * 2;

  if (dc.m_hDC == nullptr) {
    return Size(0, row_height);
  }
  const Rect title_rect(
      infostyle.window_border() + infostyle.row_rect_padding() +
      title_style.left_padding(),
      ypos + infostyle.row_rect_padding(),
      title_width, title_size.height);
  const Rect desc_rect(
      infostyle.window_border() + infostyle.row_rect_padding() +
      desc_style.left_padding(),
      ypos + infostyle.row_rect_padding() + title_rect.size.height,
      desc_width, desc_size.height);

  const CRect title_back_crect(infostyle.window_border(), ypos,
      infostyle.window_width() - infostyle.window_border(),
      ypos + title_rect.size.height + infostyle.row_rect_padding());

  const CRect desc_back_crect(infostyle.window_border(),
      ypos + title_rect.size.height + infostyle.row_rect_padding(),
      infostyle.window_width() - infostyle.window_border(),
      ypos + title_rect.size.height + infostyle.row_rect_padding() +
      desc_rect.size.height + infostyle.row_rect_padding());

  if (usages.has_focused_index() && (row == usages.focused_index())) {
    const CRect selected_rect(infostyle.window_border(), ypos,
        infostyle.window_width() - infostyle.window_border(),
        ypos + title_rect.size.height + desc_rect.size.height
         + infostyle.row_rect_padding() * 2);
    dc.FillSolidRect(&selected_rect,
        RGB(infostyle.focused_background_color().r(),
            infostyle.focused_background_color().g(),
            infostyle.focused_background_color().b()));
    dc.SetDCBrushColor(
        RGB(infostyle.focused_border_color().r(),
            infostyle.focused_border_color().g(),
            infostyle.focused_border_color().b()));
    dc.FrameRect(&selected_rect,
        static_cast<HBRUSH>(GetStockObject(DC_BRUSH)));
  } else {
    if (title_style.has_background_color()) {
      dc.FillSolidRect(&title_back_crect,
          RGB(title_style.background_color().r(),
              title_style.background_color().g(),
              title_style.background_color().b()));
    } else {
      dc.FillSolidRect(&title_back_crect,
          RGB(255, 255, 255));
    }
    if (desc_style.has_background_color()) {
      dc.FillSolidRect(&desc_back_crect,
          RGB(title_style.background_color().r(),
              title_style.background_color().g(),
              title_style.background_color().b()));
    } else {
      dc.FillSolidRect(&desc_back_crect,
          RGB(255, 255, 255));
    }
  }

  text_renderer_->RenderText(dc,  title_str,  title_rect,
      TextRenderer::FONTSET_INFOLIST_TITLE);
  text_renderer_->RenderText(dc, desc_str, desc_rect,
      TextRenderer::FONTSET_INFOLIST_DESCRIPTION);
  return Size(0, row_height);
}

void InfolistWindow::OnSettingChange(UINT uFlags, LPCTSTR /*lpszSection*/) {
  // Since TextRenderer uses dialog font to render,
  // we monitor font-related parameters to know when the font style is changed.
  switch (uFlags) {
    case 0x1049:  // = SPI_SETCLEARTYPE
    case SPI_SETFONTSMOOTHING:
    case SPI_SETFONTSMOOTHINGCONTRAST:
    case SPI_SETFONTSMOOTHINGORIENTATION:
    case SPI_SETFONTSMOOTHINGTYPE:
    case SPI_SETNONCLIENTMETRICS:
      metrics_changed_ = true;
      break;
    default:
      // We ignore other changes.
      break;
  }
}

void InfolistWindow::OnTimer(UINT_PTR nIDEvent) {
  if (nIDEvent != kIdDelayShowHideTimer) {
    return;
  }
  if (visible_) {
    DelayShow(0);
  } else {
    DelayHide(0);
  }
}

void InfolistWindow::DelayShow(UINT mseconds) {
  visible_ = true;
  KillTimer(kIdDelayShowHideTimer);
  if (mseconds <= 0) {
    const bool current_visible = (IsWindowVisible() != FALSE);
    SetWindowPos(HWND_TOPMOST, 0, 0, 0, 0,
        SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_SHOWWINDOW);
    SendMessageW(WM_NCACTIVATE, FALSE);
    if (!current_visible) {
      SendUsageStatsEvent(send_command_interface_,
          SessionCommand::INFOLIST_WINDOW_SHOW);
    }
  } else {
    SetTimer(kIdDelayShowHideTimer, mseconds, nullptr);
  }
}

void InfolistWindow::DelayHide(UINT mseconds) {
  visible_ = false;
  KillTimer(kIdDelayShowHideTimer);
  if (mseconds <= 0) {
    const bool current_visible = (IsWindowVisible() != FALSE);
    ShowWindow(SW_HIDE);
    if (current_visible) {
      SendUsageStatsEvent(send_command_interface_,
          SessionCommand::INFOLIST_WINDOW_HIDE);
    }
  } else {
    SetTimer(kIdDelayShowHideTimer, mseconds, nullptr);
  }
}

void InfolistWindow::UpdateLayout(const commands::Candidates &candidates) {
  candidates_->CopyFrom(candidates);

  // If we detect any change of font parameters, update text renderer
  if (metrics_changed_) {
    text_renderer_->OnThemeChanged();
    metrics_changed_ = false;
  }
}

void InfolistWindow::SetSendCommandInterface(
  client::SendCommandInterface *send_command_interface) {
  send_command_interface_ = send_command_interface;
}

Size InfolistWindow::GetLayoutSize() {
  CDCHandle dmyDc(nullptr);
  return DoPaint(dmyDc);
}
}  // namespace win32
}  // namespace renderer
}  // namespace mozc
