/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package com.taobao.weex.dom;

import static com.taobao.weex.dom.WXStyle.UNSET;

import android.graphics.Canvas;
import android.graphics.Typeface;
import android.os.Build;
import android.os.Looper;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.Editable;
import android.text.Layout;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.SpannedString;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.text.TextUtils;
import android.text.style.AbsoluteSizeSpan;
import android.text.style.AlignmentSpan;
import android.text.style.ForegroundColorSpan;
import android.util.Log;

import com.taobao.weex.WXEnvironment;
import com.taobao.weex.common.Constants;
import com.taobao.weex.common.WXThread;
import com.taobao.weex.dom.flex.CSSConstants;
import com.taobao.weex.dom.flex.CSSNode;
import com.taobao.weex.dom.flex.FloatUtil;
import com.taobao.weex.dom.flex.MeasureOutput;
import com.taobao.weex.ui.component.WXText;
import com.taobao.weex.ui.component.WXTextDecoration;
import com.taobao.weex.utils.WXDomUtils;
import com.taobao.weex.utils.WXLogUtils;
import com.taobao.weex.utils.WXResourceUtils;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;

/**
 * Class for calculating a given text's height and width. The calculating of width and height of
 * text is done by {@link Layout}.
 */
public class WXTextDomObject extends WXDomObject {

  /**
   * Command object for setSpan
   */
  private static class SetSpanOperation {

    protected final int start, end, flag;
    protected final Object what;

    SetSpanOperation(int start, int end, Object what) {
      this(start, end, what, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
    }

    SetSpanOperation(int start, int end, Object what, int flag) {
      this.start = start;
      this.end = end;
      this.what = what;
      this.flag = flag;
    }

    public void execute(Spannable sb) {
      sb.setSpan(what, start, end, flag);
    }
  }

  /**
   * Object for calculating text's width and height. This class is an anonymous class of
   * implementing {@link com.taobao.weex.dom.flex.CSSNode.MeasureFunction}
   */
  /** package **/ static final CSSNode.MeasureFunction TEXT_MEASURE_FUNCTION = new CSSNode.MeasureFunction() {
    @Override
    public void measure(CSSNode node, float width, @NonNull MeasureOutput measureOutput) {
      WXTextDomObject textDomObject = (WXTextDomObject) node;
      if (CSSConstants.isUndefined(width)) {
        width = node.cssstyle.maxWidth;
      }
      boolean forceWidth = false;
      if(width > 0){
         if(node.getParent() != null && textDomObject.mAlignment == Layout.Alignment.ALIGN_CENTER){
            forceWidth = FloatUtil.floatsEqual(width, node.getParent().getLayoutWidth());
         }
      }
      textDomObject.hasBeenMeasured = true;
      width = textDomObject.getTextWidth(textDomObject.mTextPaint,width, forceWidth);
      if(width > 0 && textDomObject.mText != null) {
        textDomObject.layout = textDomObject.createLayout(width, true, null);
        textDomObject.previousWidth = textDomObject.layout.getWidth();
        measureOutput.height = textDomObject.layout.getHeight();
        measureOutput.width = textDomObject.previousWidth;
      }else{
        measureOutput.height = 0;
        measureOutput.width = 0;
      }
    }
  };


  private static final Canvas DUMMY_CANVAS = new Canvas();
  private static final String ELLIPSIS = "\u2026";
  private boolean mIsColorSet = false;
  private boolean hasBeenMeasured = false;
  private int mColor;
  /**
   * mFontStyle can be {@link Typeface#NORMAL} or {@link Typeface#ITALIC}.
   */
  private int mFontStyle = UNSET;
  /**
   * mFontWeight can be {@link Typeface#NORMAL} or {@link Typeface#BOLD}.
   */
  private int mFontWeight = UNSET;
  private int mNumberOfLines = UNSET;
  private int mFontSize = UNSET;
  private int mLineHeight = UNSET;
  private float previousWidth = Float.NaN;
  private String mFontFamily = null;
  private String mText = null;
  private TextUtils.TruncateAt textOverflow;
  private Layout.Alignment mAlignment;
  private WXTextDecoration mTextDecoration = WXTextDecoration.NONE;
  private TextPaint mTextPaint = new TextPaint();
  private @Nullable Spanned spanned;
  private @Nullable Layout layout;
  private AtomicReference<Layout> atomicReference = new AtomicReference<>();

  /**
   * Create an instance of current class, and set {@link #TEXT_MEASURE_FUNCTION} as the
   * measureFunction
   * @see CSSNode#setMeasureFunction(MeasureFunction)
   */
  public WXTextDomObject() {
    super();
    mTextPaint.setFlags(TextPaint.ANTI_ALIAS_FLAG);
    setMeasureFunction(TEXT_MEASURE_FUNCTION);
  }

  public TextPaint getTextPaint() {
    return mTextPaint;
  }

  /**
   * Prepare the text {@link Spanned} for calculating text's size. This is done by setting
   * various text span to the text.
   * @see android.text.style.CharacterStyle
   */
  @Override
  public void layoutBefore() {
    hasBeenMeasured = false;
    updateStyleAndText();
    spanned = createSpanned(mText);
    if(hasNewLayout()){
        if(WXEnvironment.isApkDebugable()) {
          WXLogUtils.d("Previous csslayout was ignored! markLayoutSeen() never called");
        }
        markUpdateSeen();
    }
    super.dirty();
    super.layoutBefore();
  }

  @Override
  public void layoutAfter() {
    if (hasBeenMeasured) {
      if (layout != null &&
          !FloatUtil.floatsEqual(WXDomUtils.getContentWidth(this), previousWidth)) {
        recalculateLayout();
      }
    } else {
      updateStyleAndText();
      recalculateLayout();
    }
    hasBeenMeasured = false;
    if (layout != null && !layout.equals(atomicReference.get()) &&
        Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
      if(Thread.currentThread() != Looper.getMainLooper().getThread()){
          warmUpTextLayoutCache(layout);
      }
    }
    swap();
    super.layoutAfter();
  }

  @Override
  public Layout getExtra() {
    return atomicReference.get();
  }

  @Override
  public void updateAttr(Map<String, Object> attrs) {
    swap();
    super.updateAttr(attrs);
    if (attrs.containsKey(Constants.Name.VALUE)) {
      mText = WXAttr.getValue(attrs);
    }
  }

  @Override
  public void updateStyle(Map<String, Object> styles) {
    swap();
    super.updateStyle(styles);
    updateStyleImp(styles);
  }

  @Override
  public WXTextDomObject clone() {
    if(isCloneThis()){
      return  this;
    }
    WXTextDomObject dom = null;
    try {
      dom = new WXTextDomObject();
      copyFields(dom);
      dom.hasBeenMeasured = hasBeenMeasured;
      dom.atomicReference = new AtomicReference<>(atomicReference.get());
    } catch (Exception e) {
      if (WXEnvironment.isApkDebugable()) {
        WXLogUtils.e("WXTextDomObject clone error: ", e);
      }
    }
    if (dom != null) {
      dom.spanned = spanned;
    }
    return dom;
  }

  /**
   * RecalculateLayout.
   */
  private void recalculateLayout() {
    float contentWidth = WXDomUtils.getContentWidth(this);
    if (contentWidth > 0) {
      spanned = createSpanned(mText);
      if(mText != null){
         layout = createLayout(contentWidth, true, layout);
         previousWidth = layout.getWidth();
      }else{
         previousWidth = 0;
      }
    }
  }

  /**
   * Update style and text.
   */
  private void updateStyleAndText() {
    updateStyleImp(getStyles());
    mText = WXAttr.getValue(getAttrs());
  }

  /**
   * Record the property according to the given style
   * @param style the give style.
   */
  private void updateStyleImp(Map<String, Object> style) {
    if (style != null) {
      if (style.containsKey(Constants.Name.LINES)) {
        int lines = WXStyle.getLines(style);
        mNumberOfLines = lines > 0 ? lines : UNSET;
      }
      if (style.containsKey(Constants.Name.FONT_SIZE)) {
        mFontSize = WXStyle.getFontSize(style,getViewPortWidth());
      }
      if (style.containsKey(Constants.Name.FONT_WEIGHT)) {
        mFontWeight = WXStyle.getFontWeight(style);
      }
      if (style.containsKey(Constants.Name.FONT_STYLE)) {
        mFontStyle = WXStyle.getFontStyle(style);
      }
      if (style.containsKey(Constants.Name.COLOR)) {
        mColor = WXResourceUtils.getColor(WXStyle.getTextColor(style));
        mIsColorSet = mColor != Integer.MIN_VALUE;
      }
      if (style.containsKey(Constants.Name.TEXT_DECORATION)) {
        mTextDecoration = WXStyle.getTextDecoration(style);
      }
      if (style.containsKey(Constants.Name.FONT_FAMILY)) {
        mFontFamily = WXStyle.getFontFamily(style);
      }
      mAlignment = WXStyle.getTextAlignment(style);
      textOverflow = WXStyle.getTextOverflow(style);
      int lineHeight = WXStyle.getLineHeight(style,getViewPortWidth());
      if (lineHeight != UNSET) {
        mLineHeight = lineHeight;
      }
    }
  }

  /**
   * Update layout according to {@link #mText} and span
   * @param width the specified width.
   * @param forceWidth If true, force the text width to the specified width, otherwise, text width
   *                   may equals to or be smaller than the specified width.
   * @param previousLayout the result of previous layout, could be null.
   */
  private
  @NonNull
  Layout createLayout(float width, boolean forceWidth, @Nullable Layout previousLayout) {
    float textWidth;
    textWidth = getTextWidth(mTextPaint, width, forceWidth);
    Layout layout;
    if (!FloatUtil.floatsEqual(previousWidth, textWidth) || previousLayout == null) {
      layout = new StaticLayout(spanned, mTextPaint, (int) Math.ceil(textWidth),
          Layout.Alignment.ALIGN_NORMAL, 1, 0, false);
    } else {
      layout = previousLayout;
    }
    if (mNumberOfLines != UNSET && mNumberOfLines > 0 && mNumberOfLines < layout.getLineCount()) {
      int lastLineStart, lastLineEnd;
      lastLineStart = layout.getLineStart(mNumberOfLines - 1);
      lastLineEnd = layout.getLineEnd(mNumberOfLines - 1);
      if (lastLineStart < lastLineEnd) {
        SpannableStringBuilder builder = new SpannableStringBuilder(spanned.subSequence(0, lastLineStart));
        Editable lastLine = new SpannableStringBuilder(spanned.subSequence(lastLineStart, lastLineEnd));
        builder.append(truncate(lastLine, mTextPaint, layout.getWidth(), textOverflow));
        adjustSpansRange(spanned, builder);
        spanned = builder;
        return new StaticLayout(spanned, mTextPaint, (int) Math.ceil(textWidth),
            Layout.Alignment.ALIGN_NORMAL, 1, 0, false);
      }
    }
    return layout;
  }

  /**
   * Truncate the source span to the specified lines.
   * Caller of this method must ensure that the lines of text is <strong>greater than desired lines and need truncate</strong>.
   * Otherwise, unexpected behavior may happen.
   * @param source The source span.
   * @param paint the textPaint
   * @param desired specified lines.
   * @param truncateAt truncate method, null value means clipping overflow text directly, non-null value means using ellipsis strategy to clip
   * @return The spans after clipped.
   */
  private
  @NonNull
  Spanned truncate(@Nullable Editable source, @NonNull TextPaint paint,
      int desired, @Nullable TextUtils.TruncateAt truncateAt) {
    Spanned ret = new SpannedString("");
    if (!TextUtils.isEmpty(source) && source.length() > 0) {
      if (truncateAt != null) {
        source.append(ELLIPSIS);
      }

      StaticLayout layout;
      int startOffset;

      while (source.length() > 1) {
        startOffset = source.length() -1;
        if (truncateAt != null) {
          startOffset -= 1;
        }
        source.delete(startOffset, startOffset+1);
        layout = new StaticLayout(source, paint, desired, Layout.Alignment.ALIGN_NORMAL, 1, 0, true);
        if (layout.getLineCount() <= 1) {
          ret = source;
          break;
        }
      }
    }
    return ret;
  }

  /**
   * Adjust span range after truncate due to the wrong span range during span copy and slicing.
   * @param beforeTruncate The span before truncate
   * @param afterTruncate The span after truncate
   */
  private void adjustSpansRange(@NonNull Spanned beforeTruncate, @NonNull Spannable afterTruncate){
    Object[] spans = beforeTruncate.getSpans(0, beforeTruncate.length(), Object.class);
    for(Object span:spans){
      int start = beforeTruncate.getSpanStart(span);
      int end = beforeTruncate.getSpanEnd(span);
      if(start == 0 && end == beforeTruncate.length()){
        afterTruncate.removeSpan(span);
        afterTruncate.setSpan(span, 0, afterTruncate.length(), beforeTruncate.getSpanFlags(span));
      }
    }
  }

  /**
   * Get text width according to constrain of outerWidth with and forceToDesired
   * @param textPaint paint used to measure text
   * @param outerWidth the width that css-layout desired.
   * @param forceToDesired if set true, the return value will be outerWidth, no matter what the width
   *                   of text is.
   * @return if forceToDesired is false, it will be the minimum value of the width of text and
   * outerWidth in case of outerWidth is defined, in other case, it will be outer width.
   */
   float getTextWidth(TextPaint textPaint,float outerWidth, boolean forceToDesired) {
     if(mText == null){
       if(forceToDesired){
         return  outerWidth;
       }
        return  0;
     }
    float textWidth;
    if (forceToDesired) {
      textWidth = outerWidth;
    } else {
      float desiredWidth = Layout.getDesiredWidth(spanned, textPaint);
      if (CSSConstants.isUndefined(outerWidth) || desiredWidth < outerWidth) {
        textWidth = desiredWidth;
      } else {
        textWidth = outerWidth;
      }
    }
    return textWidth;
  }

  /**
   * Update {@link #spanned} according to the give charSequence and styles
   * @param text the give raw text.
   * @return an Spanned contains text and spans
   */
  protected
  @NonNull
  Spanned createSpanned(String text) {
    if (!TextUtils.isEmpty(text)) {
      SpannableString spannable = new SpannableString(text);
      updateSpannable(spannable, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
      return spannable;
    }
    return new SpannableString("");
  }

  protected void updateSpannable(Spannable spannable, int spanFlag) {
    List<SetSpanOperation> ops = createSetSpanOperation(spannable.length(), spanFlag);
    if (mFontSize == UNSET) {
      ops.add(new SetSpanOperation(0, spannable.length(),
          new AbsoluteSizeSpan(WXText.sDEFAULT_SIZE), spanFlag));
    }
    Collections.reverse(ops);
    for (SetSpanOperation op : ops) {
      op.execute(spannable);
    }
  }

  /**
   * Create a task list which contains {@link SetSpanOperation}. The task list will be executed
   * in other method.
   * @param end the end character of the text.
   * @return a task list which contains {@link SetSpanOperation}.
   */
  private List<SetSpanOperation> createSetSpanOperation(int end, int spanFlag) {
    List<SetSpanOperation> ops = new LinkedList<>();
    int start = 0;
    if (end >= start) {
      if (mTextDecoration == WXTextDecoration.UNDERLINE || mTextDecoration == WXTextDecoration.LINETHROUGH) {
        ops.add(new SetSpanOperation(start, end, new TextDecorationSpan(mTextDecoration), spanFlag));
      }
      if (mIsColorSet) {
        ops.add(new SetSpanOperation(start, end,
            new ForegroundColorSpan(mColor), spanFlag));
      }
      if (mFontSize != UNSET) {
        ops.add(new SetSpanOperation(start, end, new AbsoluteSizeSpan(mFontSize), spanFlag));
      }
      if (mFontStyle != UNSET
          || mFontWeight != UNSET
          || mFontFamily != null) {
        ops.add(new SetSpanOperation(start, end,
            new WXCustomStyleSpan(mFontStyle, mFontWeight, mFontFamily),
            spanFlag));
      }
      ops.add(new SetSpanOperation(start, end, new AlignmentSpan.Standard(mAlignment), spanFlag));
      if (mLineHeight != UNSET) {
        ops.add(new SetSpanOperation(start, end, new WXLineHeightSpan(mLineHeight), spanFlag));
      }
    }
    return ops;
  }

  /**
   * Move the reference of current layout to the {@link AtomicReference} for further use,
   * then clear current layout.
   */
  private void swap() {
    if (layout != null) {
      atomicReference.set(layout);
      layout = null;
      mTextPaint = new TextPaint(mTextPaint);
    }
    hasBeenMeasured = false;
  }

  /**
   * As warming up TextLayoutCache done in the DOM thread may manipulate UI operation,
   there may be some exception, in which case the exception is ignored. After all,
   this is just a warm up operation.
   * @return false for warm up failure, otherwise returns true.
   */
  private boolean warmUpTextLayoutCache(Layout layout) {
    boolean result;
    try {
      layout.draw(DUMMY_CANVAS);
      result = true;
    } catch (Exception e) {
      WXLogUtils.eTag(TAG, e);
      result = false;
    }
    return result;
  }
}
