// 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.protobuf.ProtoCandidates.CandidateList;
import org.mozc.android.inputmethod.japanese.protobuf.ProtoCandidates.CandidateWord;
import org.mozc.android.inputmethod.japanese.ui.CandidateLayout.Row;
import org.mozc.android.inputmethod.japanese.ui.CandidateLayout.Span;
import org.mozc.android.inputmethod.japanese.view.CarrierEmojiRenderHelper;
import org.mozc.android.inputmethod.japanese.view.Skin;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;

import android.annotation.SuppressLint;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.text.Layout;
import android.text.Layout.Alignment;
import android.text.StaticLayout;
import android.text.TextPaint;

import java.util.List;
import java.util.Locale;

/**
 * Renders the {@link CandidateLayout} instance to the {@link Canvas}.
 * After set all the parameter, clients can render the CandidateLayout as follows.
 *
 * {@code
 * CandidateList candidateList = ...;
 * CandidateLayoutRenderer renderer = ...;
 * CandidateLayout candidateLayout = layouter.layout(candidateList);
 *   :
 *   :
 * // it is necessary to set the original CandidateList before the actual rendering.
 * renderer.setCandidateList(candidateList);
 *   :
 *   :
 * renderer.drawCandidateLayout(canvas, candidateLayout, pressedCandidateIndex);
 *   :
 *   :
 * // If the original candidateList is same, it's ok to invoke the rendering
 * // twice or more, without re-invoking the setCandidateList.
 * renderer.drawCandidateLayout(canvas, candidateLayout, pressedCandidateIndex);
 * }
 */
public class CandidateLayoutRenderer {

  /**
   * The layout value width may be shorter than the rendered value without any settings.
   * This policy sets how to compress (scale) the value.
   */
  public enum ValueScalingPolicy {

    /** Scales uniformly (in other words, the aspect ratio will be kept). */
    UNIFORM,

    /** Scales only horizontally, so the height of the text will be kept. */
    HORIZONTAL,
  }

  /** Specifies if the description can keep its own region or not. */
  public enum DescriptionLayoutPolicy {

    /** The description's region will be shared with the value's. */
    OVERLAY,

    /**
     * The description can keep its region exclusively (i.e., the value and description
     * won't be overlapped).
     */
    EXCLUSIVE,

    /**
     * Like View.GONE, the descriptor is not shown and doesn't occupy any are.
     */
    GONE,
  }

  private static final int[] STATE_EMPTY = {};

  // This is actually not the constant, but we should treat this as constant.
  // Should not edit its contents.
  private static final int[] STATE_FOCUSED = { android.R.attr.state_focused };

  /** 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 final TextPaint valuePaint = createTextPaint(true, Color.BLACK, Align.LEFT);
  private final TextPaint focusedValuePaint = createTextPaint(true, Color.BLACK, Align.LEFT);
  private final TextPaint descriptionPaint = createTextPaint(true, Color.GRAY, Align.RIGHT);
  private final Paint separatorPaint = new Paint();

  /**
   * The cache of Rect instance for the clip used in drawCandidateList method to reduce the
   * number of resource allocation.
   */
  private final Rect clipBounds = new Rect();

  private float valueTextSize = 0;
  private float valueHorizontalPadding = 0;

  private float descriptionTextSize = 0;
  private float descriptionHorizontalPadding = 0;
  private float descriptionVerticalPadding = 0;

  private ValueScalingPolicy valueScalingPolicy = ValueScalingPolicy.UNIFORM;
  private DescriptionLayoutPolicy descriptionLayoutPolicy = DescriptionLayoutPolicy.OVERLAY;

  private Optional<Drawable> spanBackgroundDrawable = Optional.absent();
  @VisibleForTesting int focusedIndex = -1;

  public CandidateLayoutRenderer() {
  }

  @SuppressLint("NewApi")
  private static TextPaint createTextPaint(boolean antiAlias, int color, Align align) {
    TextPaint textPaint = new TextPaint();
    textPaint.setAntiAlias(antiAlias);
    textPaint.setColor(color);
    textPaint.setTextAlign(Preconditions.checkNotNull(align));
    if (TEXT_LOCALE.isPresent()) {
      textPaint.setTextLocale(TEXT_LOCALE.get());
    }
    return textPaint;
  }

  private static boolean isFocused(
      CandidateWord candidateWord, int focusedIndex, int pressedCandidateIndex) {
    int index = Preconditions.checkNotNull(candidateWord).getIndex();
    return (index == focusedIndex) || (index == pressedCandidateIndex);
  }

  public void setSkin(Skin skin) {
    Preconditions.checkNotNull(skin);
    valuePaint.setColor(skin.candidateValueTextColor);
    focusedValuePaint.setColor(skin.candidateValueFocusedTextColor);
    descriptionPaint.setColor(skin.candidateDescriptionTextColor);
  }

  public void setValueTextSize(float valueTextSize) {
    this.valueTextSize = valueTextSize;
    this.valuePaint.setTextSize(valueTextSize);
  }

  public void setValueHorizontalPadding(float valueHorizontalPadding) {
    this.valueHorizontalPadding = valueHorizontalPadding;
  }

  public void setDescriptionTextSize(float descriptionTextSize) {
    this.descriptionTextSize = descriptionTextSize;
    this.descriptionPaint.setTextSize(descriptionTextSize);
  }

  public void setDescriptionHorizontalPadding(float descriptionHorizontalPadding) {
    this.descriptionHorizontalPadding = descriptionHorizontalPadding;
  }

  public void setDescriptionVerticalPadding(float descriptionVerticalPadding) {
    this.descriptionVerticalPadding = descriptionVerticalPadding;
  }

  public void setValueScalingPolicy(ValueScalingPolicy valueScalingPolicy) {
    this.valueScalingPolicy = Preconditions.checkNotNull(valueScalingPolicy);
  }

  public void setDescriptionLayoutPolicy(DescriptionLayoutPolicy descriptionLayoutPolicy) {
    this.descriptionLayoutPolicy = Preconditions.checkNotNull(descriptionLayoutPolicy);
  }

  public void setSpanBackgroundDrawable(Optional<Drawable> drawable) {
    this.spanBackgroundDrawable = Preconditions.checkNotNull(drawable);
  }

  public void setCandidateList(Optional<CandidateList> candidateList) {
    Preconditions.checkNotNull(candidateList);
    focusedIndex = (candidateList.isPresent() && candidateList.get().hasFocusedIndex())
        ? candidateList.get().getFocusedIndex()
        : -1;
  }

  public void setSeparatorWidth(float separatorWidth) {
    separatorPaint.setStrokeWidth(separatorWidth);
  }

  public void setSeparatorColor(int color) {
    separatorPaint.setColor(color);
  }

  /**
   * Renders the {@code candidateLayout} to the given {@code canvas}.
   */
  public void drawCandidateLayout(
      Canvas canvas, CandidateLayout candidateLayout, int pressedCandidateIndex,
      CarrierEmojiRenderHelper carrierEmojiRenderHelper) {
    Preconditions.checkNotNull(canvas);
    Preconditions.checkNotNull(candidateLayout);

    Rect clipBounds = this.clipBounds;
    canvas.getClipBounds(clipBounds);

    int focusedIndex = this.focusedIndex;
    for (Row row : candidateLayout.getRowList()) {
      float top = row.getTop();
      if (top > clipBounds.bottom) {
        break;
      }
      if (top + row.getHeight() < clipBounds.top) {
        continue;
      }

      float separatorMargin = row.getHeight() * 0.2f;
      float separatorTop = row.getTop() + separatorMargin;
      float separatorBottom = row.getTop() + row.getHeight() - separatorMargin;

      for (Span span : row.getSpanList()) {
        if (span.getLeft() > clipBounds.right) {
          break;
        }
        if (span.getRight() < clipBounds.left) {
          continue;
        }
        // Even if span.getCandidateWord() is absent, draw the span in order to draw the background.
        drawSpan(canvas, row, span,
                 span.getCandidateWord().isPresent()
                     && isFocused(span.getCandidateWord().get(),
                                  focusedIndex, pressedCandidateIndex),
                 carrierEmojiRenderHelper);
        if (span.getLeft() != 0f) {
          float separatorX = span.getLeft();
          canvas.drawLine(separatorX, separatorTop, separatorX, separatorBottom, separatorPaint);
        }
      }
    }
  }

  @VisibleForTesting void drawSpan(
      Canvas canvas, Row row, Span span, boolean isFocused,
      CarrierEmojiRenderHelper carrierEmojiRenderHelper) {
    drawSpanBackground(
        Preconditions.checkNotNull(canvas), Preconditions.checkNotNull(row), span, isFocused);
    if (!span.getCandidateWord().isPresent()) {
      return;
    }

    if (carrierEmojiRenderHelper.isRenderableEmoji(span.getCandidateWord().get().getValue())) {
      drawCarrierEmoji(canvas, row, span, carrierEmojiRenderHelper);
    } else {
      drawText(canvas, row, span, isFocused);
    }

    drawDescription(canvas, row, span);
  }

  private void drawSpanBackground(Canvas canvas, Row row, Span span, boolean isFocused) {
    if (!this.spanBackgroundDrawable.isPresent()) {
      // No background available.
      return;
    }

    Drawable spanBackgroundDrawable = this.spanBackgroundDrawable.get();
    spanBackgroundDrawable.setBounds(
        (int) span.getLeft(), (int) row.getTop(),
        (int) span.getRight(), (int) (row.getTop() + row.getHeight()));
    spanBackgroundDrawable.setState(isFocused ? STATE_FOCUSED : STATE_EMPTY);
    spanBackgroundDrawable.draw(canvas);
  }

  private void drawCarrierEmoji(
      Canvas canvas, Row row, Span span, CarrierEmojiRenderHelper carrierEmojiRenderHelper) {
    Preconditions.checkState(span.getCandidateWord().isPresent());

    float descriptionWidth = (descriptionLayoutPolicy == DescriptionLayoutPolicy.EXCLUSIVE)
        ? span.getDescriptionWidth() : 0;
    float centerX = span.getLeft() + (span.getWidth() - descriptionWidth) / 2;
    float centerY = row.getTop() + row.getHeight() / 2;

    carrierEmojiRenderHelper.drawEmoji(canvas, span.getCandidateWord().get(), centerX, centerY);
  }

  private void drawText(Canvas canvas, Row row, Span span, boolean isFocused) {
    Preconditions.checkState(span.getCandidateWord().isPresent());

    String valueText = span.getCandidateWord().get().getValue();
    if (valueText == null || valueText.length() == 0) {
      // No value is available.
      return;
    }
    // Calculate layout or get cached one.
    // If isFocused is true, special paint should be applied.
    // The resulting drawing is so special that it will not re reused.
    // Therefore if isFocused is true cache is not used and always calculate the layout.
    // In this case calculated layout is not cached.
    Layout layout;
    if (!isFocused && span.getCachedLayout().isPresent()) {
      layout = span.getCachedLayout().get();
    } else {
      // Set the scaling of the text.
      float descriptionWidth = (descriptionLayoutPolicy == DescriptionLayoutPolicy.EXCLUSIVE)
          ? span.getDescriptionWidth() : 0;
      // Ensure that StaticLayout instance has positive width.
      float displayValueWidth =
          Math.max(1f, span.getWidth() - valueHorizontalPadding * 2 - descriptionWidth);
      float textScale = Math.min(1f, displayValueWidth / span.getValueWidth());
      TextPaint textPaint = isFocused ? this.focusedValuePaint : this.valuePaint;
      if (valueScalingPolicy == ValueScalingPolicy.HORIZONTAL) {
        textPaint.setTextSize(valueTextSize);
        textPaint.setTextScaleX(textScale);
      } else {
        // Calculate the max limit of the "text size", in which we can render the candidate text
        // inside the given span.
        // Rendered text should be inside the givenWidth.
        // Adjustment by font size can keep aspect ratio,
        // which is important for Emoticon especially.
        // Calculate the width with the default text size.
        textPaint.setTextSize(valueTextSize * textScale);
      }
      // Layout's width is theoretically `span.getWidth() - descriptionWidth`.
      // However because of the spec of Paint#setTextScaleX() and Paint#setTextSize(),
      // Paint#measureText() might return larger width than what both above methods expect it to be.
      // As a workaround, if theoretical width is smaller than the result of Paint#measureText(),
      // employ the width returned by Paint#measureText().
      // This workaround is to avoid from unexpected line-break.
      // NOTE: Canvas#scale() cannot be used here because we have to use StaticLayout to draw
      //       Emoji and StaticLayout requires width in its constructor.
      layout = new StaticLayout(
          valueText, new TextPaint(textPaint),
          (int) Math.ceil(Math.max(span.getWidth() - descriptionWidth,
                                   textPaint.measureText(valueText))),
          Alignment.ALIGN_CENTER, 1, 0, false);
      if (!isFocused) {
        span.setCachedLayout(layout);
      }
    }

    // Actually render the image to the canvas.
    int saveCount = canvas.save();
    try {
      canvas.translate(span.getLeft(), row.getTop() + (row.getHeight() - layout.getHeight()) / 2);
      layout.draw(canvas);
    } finally {
      canvas.restoreToCount(saveCount);
    }
  }

  private void drawDescription(Canvas canvas, Row row, Span span) {
    List<String> descriptionList = span.getSplitDescriptionList();
    if (span.getDescriptionWidth() <= 0 || descriptionList.isEmpty()
        || descriptionLayoutPolicy == DescriptionLayoutPolicy.GONE) {
      // No description available or the layout policy is GONE.
      return;
    }

    // Set the x-orientation scale based on the description's width to fit the span's region.
    TextPaint descriptionPaint = this.descriptionPaint;
    descriptionPaint.setTextSize(descriptionTextSize);
    float centerOrRight;
    if (descriptionLayoutPolicy == DescriptionLayoutPolicy.OVERLAY) {
      float displayWidth = span.getWidth() - descriptionHorizontalPadding * 2;
      descriptionPaint.setTextScaleX(Math.min(1f, displayWidth / span.getDescriptionWidth()));
      descriptionPaint.setTextAlign(Align.CENTER);
      centerOrRight = (span.getLeft() + span.getRight()) / 2f;
    } else {
      descriptionPaint.setTextScaleX(1f);
      descriptionPaint.setTextAlign(Align.RIGHT);
      centerOrRight = span.getRight() - descriptionHorizontalPadding;
    }

    // Render first "N" description lines based on the layout height.
    float descriptionTextSize = this.descriptionTextSize;
    float descriptionHeight = row.getHeight() - descriptionVerticalPadding * 2;
    int numDescriptionLines =
        Math.min((int) (descriptionHeight / descriptionTextSize), descriptionList.size());

    float top = row.getTop() + row.getHeight()
        - descriptionVerticalPadding - descriptionTextSize * (numDescriptionLines - 1);
    for (String description : descriptionList.subList(0, numDescriptionLines)) {
      canvas.drawText(description, centerOrRight, top, descriptionPaint);
      top += descriptionTextSize;
    }
  }
}
