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

package org.mozc.android.inputmethod.japanese.ui;

import org.mozc.android.inputmethod.japanese.MozcUtil;
import org.mozc.android.inputmethod.japanese.ViewEventListener;
import org.mozc.android.inputmethod.japanese.protobuf.ProtoCandidates.Candidates;
import org.mozc.android.inputmethod.japanese.protobuf.ProtoCandidates.Candidates.Candidate;
import org.mozc.android.inputmethod.japanese.protobuf.ProtoCandidates.Category;
import org.mozc.android.inputmethod.japanese.protobuf.ProtoCommands.Command;
import org.mozc.android.inputmethod.japanese.resources.R;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;

import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Paint.FontMetrics;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Build;
import android.view.MotionEvent;

import java.util.Locale;

/**
 * Layouts floating candidate window and draw it's contents on canvas.
 *
 * The point of origin of layout is NOT a left-top corner of candidate list BUT the left-top corner
 * of the candidate column and the right-top corner of the shortcut column.
 *
 * TODO(hsumita): Rewrite using LinearLayout or something.
 */
public class FloatingCandidateLayoutRenderer {

  private static class WindowRects {

    public final Rect window;
    public final Optional<Rect> focus;
    public final Optional<Rect> pageIndicator;
    public final Optional<RectF> scrollIndicator;

    WindowRects(Rect window, Optional<Rect> focus, Optional<Rect> pageIndicator,
                Optional<RectF> scrollIndicator) {
      this.window = Preconditions.checkNotNull(window);
      this.focus = Preconditions.checkNotNull(focus);
      this.pageIndicator = Preconditions.checkNotNull(pageIndicator);
      this.scrollIndicator = Preconditions.checkNotNull(scrollIndicator);
    }
  }

  /** Locale field for {@link Paint#setTextLocale(Locale)}. */
  private static final Optional<Locale> TEXT_LOCALE = (Build.VERSION.SDK_INT >= 17)
      ? Optional.of(Locale.JAPAN) : Optional.<Locale>absent();

  private static final String FOOTER_TEXT_FORMAT = "%d / %d";

  private final Paint candidatePaint;
  private final Paint focusedCandidatePaint;
  private final Paint descriptionPaint;
  private final Paint shortcutPaint;
  private final Paint footerPaint;
  private final Paint separatorPaint;
  private final Paint windowBackgroundPaint;
  private final Paint focuseBackgroundPaint;
  private final Paint scrollIndicatorPaint;

  private final int windowMinimumWidth;
  private final int windowHorizontalPadding;
  private final float windowRoundRectRadius;
  private final int candidateHeight;
  private final int candidateOffsetY;
  private final int candidateDescriptionMinimumPadding;
  private final int footerHeight;
  private final float footerTextCenterToBaseLineOffset;
  private final int horizontalSeparatorPadding;
  private final int shortcutWidth;
  private final float shortcutCenterX;
  private final int scrollIndicatorWidth;
  private final int scrollIndicatorRadius;

  private Optional<WindowRects> windowRects = Optional.absent();
  private Optional<ViewEventListener> viewEventListener = Optional.absent();
  private Optional<Candidates> candidates = Optional.absent();
  private Optional<Integer> maxWidth = Optional.absent();
  /** Focused candidate index, or tapped candidate index if exists. */
  private Optional<Integer> focusedOrTappedCandidateIndexOnPage = Optional.absent();
  /** TappedInfo for the current touch operation. Set on TOUCH_DOWN, reset on TOUCH_UP. */
  private Optional<Integer> tappingCandidateIndex = Optional.absent();
  private int totalCandidatesCount;
  private int maxCandidateWidth;
  private int maxDescriptionWidth;

  public FloatingCandidateLayoutRenderer(Resources res) {
    Preconditions.checkNotNull(res);

    candidatePaint = new Paint();
    candidatePaint.setColor(res.getColor(R.color.floating_candidate_text));
    candidatePaint.setTextSize(res.getDimension(R.dimen.floating_candidate_text_size));
    candidatePaint.setAntiAlias(true);
    if (TEXT_LOCALE.isPresent()) {
      candidatePaint.setTextLocale(TEXT_LOCALE.get());
    }

    focusedCandidatePaint = new Paint(candidatePaint);
    focusedCandidatePaint.setColor(res.getColor(R.color.floating_candidate_focused_text));

    descriptionPaint = new Paint(candidatePaint);
    descriptionPaint.setTextSize(
        res.getDimension(R.dimen.floating_candidate_description_text_size));
    descriptionPaint.setColor(res.getColor(R.color.floating_candidate_description_text));

    shortcutPaint = new Paint(candidatePaint);
    shortcutPaint.setTextSize(res.getDimension(R.dimen.floating_candidate_shortcut_text_size));
    shortcutPaint.setColor(res.getColor(R.color.floating_candidate_shortcut_text));

    scrollIndicatorPaint = new Paint();
    scrollIndicatorPaint.setColor(res.getColor(R.color.floating_candidate_scroll_indicator));

    footerPaint = new Paint(candidatePaint);
    footerPaint.setTextSize(res.getDimension(R.dimen.floating_candidate_footer_text_size));
    footerPaint.setColor(res.getColor(R.color.floating_candidate_footer_text));

    separatorPaint = new Paint();
    separatorPaint.setStrokeWidth(
        res.getDimension(R.dimen.floating_candidate_separator_width));
    separatorPaint.setColor(res.getColor(R.color.floating_candidate_footer_separator));

    windowBackgroundPaint = new Paint();
    windowBackgroundPaint.setColor(res.getColor(R.color.floating_candidate_window_background));
    windowBackgroundPaint.setShadowLayer(
        res.getDimension(R.dimen.floating_candidate_window_shadow_radius),
        0, res.getDimension(R.dimen.floating_candidate_window_shadow_offset_y),
        res.getColor(R.color.floating_candidate_shadow));

    focuseBackgroundPaint = new Paint();
    focuseBackgroundPaint.setColor(res.getColor(R.color.floating_candidate_focus_background));

    float candidateVerticalPadding =
        res.getDimension(R.dimen.floating_candidate_candidate_vertical_padding);
    FontMetrics candidateMetrics = candidatePaint.getFontMetrics();
    candidateHeight = (int) Math.ceil(
        candidateMetrics.descent - candidateMetrics.ascent + candidateVerticalPadding * 2);
    candidateOffsetY = (int) Math.ceil(-candidateMetrics.ascent + candidateVerticalPadding);

    windowMinimumWidth = res.getDimensionPixelSize(R.dimen.floating_candidate_window_minimum_width);
    windowHorizontalPadding =
        res.getDimensionPixelOffset(R.dimen.floating_candidate_window_horizontal_padding);
    windowRoundRectRadius = res.getDimension(R.dimen.floating_candidate_window_round_rect_radius);
    candidateDescriptionMinimumPadding =
        res.getDimensionPixelSize(R.dimen.floating_candidate_candidate_description_minimum_padding);
    horizontalSeparatorPadding =
        res.getDimensionPixelSize(R.dimen.floating_candidate_separator_horizontal_padding);

    scrollIndicatorWidth =
        res.getDimensionPixelSize(R.dimen.floating_candidate_scroll_indicator_width);
    scrollIndicatorRadius =
        res.getDimensionPixelSize(R.dimen.floating_candidate_scroll_indicator_radius);

    FontMetrics footerMetrics = footerPaint.getFontMetrics();
    float footerTextHeight = -footerMetrics.ascent + footerMetrics.descent;
    footerHeight = Math.round(footerTextHeight * 2f);
    footerTextCenterToBaseLineOffset = (-footerMetrics.ascent - footerMetrics.descent) / 2f;

    float shortcutCharacterWidth = shortcutPaint.measureText("m");
    float shortcutCandidatePadding =
        res.getDimensionPixelSize(R.dimen.floating_candidate_shortcut_candidate_padding);
    shortcutWidth = Math.round(shortcutCharacterWidth + shortcutCandidatePadding);
    shortcutCenterX = -shortcutCharacterWidth / 2f - shortcutCandidatePadding;

    updateLayout();
  }

  /** Handle touch event and invoke some actions. */
  public void onTouchEvent(MotionEvent event) {
    if (!candidates.isPresent() || !viewEventListener.isPresent()) {
      return;
    }
    ViewEventListener listener = viewEventListener.get();

    Optional<Integer> optionalCandidateIndex = getTappingCandidate(event);

    if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
      tappingCandidateIndex = optionalCandidateIndex;
      updateLayout();
      return;
    }
    if (event.getActionMasked() != MotionEvent.ACTION_UP) {
      return;
    }

    if (!optionalCandidateIndex.isPresent() || !tappingCandidateIndex.isPresent()
        || !optionalCandidateIndex.equals(tappingCandidateIndex)) {
      tappingCandidateIndex = Optional.absent();
      updateLayout();
      return;
    }
    int candidateIndex = optionalCandidateIndex.get();
    tappingCandidateIndex = Optional.absent();

    listener.onConversionCandidateSelected(
        candidates.get().getCandidate(candidateIndex).getId(),
        Optional.<Integer>absent());
  }

  /** Sets the max width of this window. */
  public void setMaxWidth(int maxWidth) {
    if (maxWidth > 0) {
      this.maxWidth = Optional.of(maxWidth);
    } else {
      this.maxWidth = Optional.absent();
    }
    updateLayout();
  }

  /** Sets candidates. */
  public void setCandidates(Command outCommand) {
    Preconditions.checkNotNull(outCommand);
    if (outCommand.getOutput().getCandidates().getCandidateCount() == 0) {
      candidates = Optional.<Candidates>absent();
      totalCandidatesCount = 0;
    } else {
      candidates = Optional.of(outCommand.getOutput().getCandidates());
      totalCandidatesCount = outCommand.getOutput().getAllCandidateWords().getCandidatesCount();
    }
    updateLayout();
  }

  /** Sets a view event listener to handle touch events. */
  public void setViewEventListener(ViewEventListener listener) {
    viewEventListener = Optional.of(listener);
  }

  /**
   * Gets the rectangle of this window.
   * Defensive-copied value is returned so caller-side can modify it.
   */
  public Optional<Rect> getWindowRect() {
    if (windowRects.isPresent()) {
      return Optional.of(new Rect(windowRects.get().window));
    } else {
      return Optional.absent();
    }
  }

  /** Draws this candidate window. */
  public void draw(Canvas canvas) {
    Preconditions.checkNotNull(canvas);
    Preconditions.checkState(candidates.isPresent());
    Preconditions.checkState(windowRects.isPresent());

    Candidates candidatesData = candidates.get();
    WindowRects rects = windowRects.get();

    canvas.drawRoundRect(
        new RectF(rects.window), windowRoundRectRadius, windowRoundRectRadius,
        windowBackgroundPaint);

    if (rects.focus.isPresent()) {
      canvas.drawRect(rects.focus.get(), focuseBackgroundPaint);
    }

    // Candidates, descriptions and shortcuts.
    int focusedIndex = focusedOrTappedCandidateIndexOnPage.or(-1);
    for (int i = 0; i < candidatesData.getCandidateCount(); ++i) {
      Candidate candidate = candidatesData.getCandidate(i);
      int offsetY = getCandidateRowOffsetY(i) + candidateOffsetY;
      Paint paint = (i == focusedIndex) ? focusedCandidatePaint : candidatePaint;
      drawTextWithLimit(canvas, candidate.getValue(), paint, 0, offsetY, maxCandidateWidth);
      if (candidate.getAnnotation().hasDescription()) {
        drawTextWithAlignAndLimit(
            canvas, candidate.getAnnotation().getDescription(), descriptionPaint,
            rects.window.right - windowHorizontalPadding, offsetY,
            Align.RIGHT, maxDescriptionWidth);
      }
      if (candidate.getAnnotation().hasShortcut()) {
        drawTextWithAlign(
            canvas, candidate.getAnnotation().getShortcut(), shortcutPaint,
            shortcutCenterX, offsetY, Align.CENTER);
      }
    }

    // Footer. Don't show if suggestion mode.
    if (rects.pageIndicator.isPresent()) {
      Rect indicatorRect = rects.pageIndicator.get();
      drawHorizontalSeparator(
          canvas, separatorPaint, rects.window.left, rects.window.right, indicatorRect.top);
      drawPageIndicator(canvas, footerPaint, indicatorRect);
    }

    // Scroll indicator
    if (rects.scrollIndicator.isPresent()) {
      canvas.drawRoundRect(
          rects.scrollIndicator.get(), scrollIndicatorRadius, scrollIndicatorRadius,
          scrollIndicatorPaint);
    }
  }

  private void drawPageIndicator(Canvas canvas, Paint paint, Rect rect) {
    drawTextWithAlign(
        canvas, String.format(FOOTER_TEXT_FORMAT,
            candidates.get().getFocusedIndex() + 1, totalCandidatesCount),
        paint, rect.exactCenterX(), rect.exactCenterY() + footerTextCenterToBaseLineOffset,
        Align.CENTER);
  }

  private void drawHorizontalSeparator(Canvas canvas, Paint paint, int startX, int endX, int y) {
    canvas.drawLine(
        Math.min(startX, endX) + horizontalSeparatorPadding, y,
        Math.max(startX, endX) - horizontalSeparatorPadding, y, paint);
  }

  /**
   * Draws {@code text} into {@code canvas} with the text align and the limitation of text width.
   * <p>
   * If measured width of {@code text} is wider than maxWidth, the {@code text} is drawn with
   * horizontal compression in order to fit {@code maxWidth}.
   */
  private void drawTextWithAlignAndLimit(
      Canvas canvas, String text, Paint paint, float x, float y, Align align, float maxWidth) {
    float textWidth = paint.measureText(text);

    int saveCount = canvas.save(Canvas.MATRIX_SAVE_FLAG);
    Align originalAlign = paint.getTextAlign();
    try {
      canvas.translate(x, y);
      if (textWidth > maxWidth) {
        // Use Canvas#scale() instead of Paint#setTextScaleX() for accurate scaling.
        canvas.scale(maxWidth / textWidth, 1.0f);
      }
      paint.setTextAlign(align);
      canvas.drawText(text, 0, 0, paint);
    } finally {
      canvas.restoreToCount(saveCount);
      paint.setTextAlign(originalAlign);
    }
  }

  /** See {@link #drawTextWithAlignAndLimit}. */
  private void drawTextWithAlign(
      Canvas canvas, String text, Paint paint, float x, float y, Align align) {
    drawTextWithAlignAndLimit(canvas, text, paint, x, y, align, Float.MAX_VALUE);
  }

  /** See {@link #drawTextWithAlignAndLimit}. */
  private void drawTextWithLimit(
      Canvas canvas, String text, Paint paint, float x, float y, float maxWidth) {
    drawTextWithAlignAndLimit(canvas, text, paint, x, y, paint.getTextAlign(), maxWidth);
  }

  private Optional<Integer> getTappingCandidate(MotionEvent event) {
    if (!windowRects.isPresent()) {
      return Optional.absent();
    }

    WindowRects rects = windowRects.get();
    int x = Math.round(event.getX());
    int y = Math.round(event.getY());

    if (!rects.window.contains(x, y)) {
      return Optional.absent();
    }

    int candidateIndex = y / candidateHeight;
    if (candidateIndex < candidates.get().getCandidateCount()) {
      return Optional.of(candidateIndex);
    } else {
      return Optional.absent();
    }
  }

  private void updateLayout() {
    if (!candidates.isPresent() || !maxWidth.isPresent()) {
      windowRects = Optional.absent();
      return;
    }

    Candidates candidatesData = candidates.get();
    int candidateNumberOnPage = candidatesData.getCandidateCount();
    boolean hasShortcut = candidatesData.getCandidateCount() > 0
        && !candidatesData.getCandidate(0).getAnnotation().getShortcut().isEmpty();
    int leftEdgePosition = hasShortcut
        ? -windowHorizontalPadding - shortcutWidth : -windowHorizontalPadding;

    // Candidates and descriptions
    maxCandidateWidth = 0;
    maxDescriptionWidth = 0;
    for (int i = 0; i < candidateNumberOnPage; ++i) {
      Candidate candidate = candidatesData.getCandidate(i);
      maxCandidateWidth = Math.max(
          maxCandidateWidth, Math.round(candidatePaint.measureText(candidate.getValue())));
      maxDescriptionWidth = Math.max(
          maxDescriptionWidth,
          Math.round(descriptionPaint.measureText(candidate.getAnnotation().getDescription())));
    }
    int fixedWidth =
        -leftEdgePosition + candidateDescriptionMinimumPadding + windowHorizontalPadding;
    int flexibleWidth = maxCandidateWidth + maxDescriptionWidth;
    if (fixedWidth + flexibleWidth > maxWidth.get()) {
      int availableWidth = maxWidth.get() - fixedWidth;
      float shrinkRate = MozcUtil.clamp((float) availableWidth / flexibleWidth, 0f, 1f);
      maxDescriptionWidth = Math.round(maxDescriptionWidth * shrinkRate);
      maxCandidateWidth = availableWidth - maxDescriptionWidth;
    }
    int rightEdgePosition = Math.max(
        Math.min(windowMinimumWidth, maxWidth.get()) + leftEdgePosition,
        maxCandidateWidth + candidateDescriptionMinimumPadding + maxDescriptionWidth
            + windowHorizontalPadding);

    // Footer
    int horizontalSeparatorY = candidateHeight * candidateNumberOnPage;
    int bottomEdgePosition;
    Optional<Rect> pageIndicatorRect;
    if (candidatesData.getCategory() != Category.SUGGESTION) {
      bottomEdgePosition = horizontalSeparatorY + footerHeight;
      pageIndicatorRect = Optional.of(
          new Rect(leftEdgePosition, horizontalSeparatorY, rightEdgePosition, bottomEdgePosition));
    } else {
      bottomEdgePosition = horizontalSeparatorY;
      pageIndicatorRect = Optional.absent();
    }

    // Focus
    Optional<Rect> focusRect = Optional.absent();
    focusedOrTappedCandidateIndexOnPage = getTappedOrFocusedIndexOnPage();
    if (focusedOrTappedCandidateIndexOnPage.isPresent()) {
      int offsetY = candidateHeight * focusedOrTappedCandidateIndexOnPage.get();
      focusRect = Optional.of(new Rect(
          leftEdgePosition, offsetY, rightEdgePosition, offsetY + candidateHeight));
    } else {
      focusRect = Optional.absent();
    }

    // Scroll indicator
    Optional<RectF> scrollIndicatorRect;
    if (totalCandidatesCount > candidatesData.getPageSize()) {
      int currentPageIndex = getCurrentPageNumber() - 1;
      float scrollIndicatorHeight =
          (float) bottomEdgePosition * candidatesData.getPageSize() / totalCandidatesCount;
      float scrollIndicatorOffset = scrollIndicatorHeight * currentPageIndex;
      scrollIndicatorRect = Optional.of(new RectF(
          rightEdgePosition - scrollIndicatorWidth, scrollIndicatorOffset, rightEdgePosition,
          Math.min(bottomEdgePosition, scrollIndicatorOffset + scrollIndicatorHeight)));
    } else {
      scrollIndicatorRect = Optional.absent();
    }

    // Window
    Rect windowRect = new Rect(leftEdgePosition, 0, rightEdgePosition, bottomEdgePosition);

    windowRects = Optional.of(
        new WindowRects(windowRect, focusRect, pageIndicatorRect, scrollIndicatorRect));
  }

  private Optional<Integer> getTappedOrFocusedIndexOnPage() {
    if (tappingCandidateIndex.isPresent()) {
      return tappingCandidateIndex;
    } else if (candidates.isPresent() && candidates.get().hasFocusedIndex()) {
      return Optional.of(candidates.get().getFocusedIndex() % candidates.get().getPageSize());
    }
    return Optional.absent();
  }

  private int getCandidateRowOffsetY(int index) {
    return index * candidateHeight;
  }

  private int getCurrentPageNumber() {
    return (int) Math.ceil(
        (float) (candidates.get().getFocusedIndex() + 1) / candidates.get().getPageSize());
  }
}
