/*
 * 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.ui.view.border;

import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.RectF;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.support.annotation.NonNull;
import com.taobao.weex.base.FloatUtil;

abstract class BorderCorner {

  final static float SWEEP_ANGLE = 45;
  private float mCornerRadius = 0.0f;
  private float mPreBorderWidth = 0.0f;
  private float mPostBorderWidth = 0.0f;
  private RectF mBorderBox;
  protected float mAngleBisector;

  /**
   * Tell whether this corner has a rounded inner corner.
   * If a corner has a rounded inner corner, it has an outer corner as well.
   */
  private boolean hasInnerCorner = false;

  /**
   * Tell whether this corner has a rounded outer corner.
   */
  private boolean hasOuterCorner = false;

  private float mOvalLeft, mOvalTop, mOvalRight, mOvalBottom;

  private float mRoundCornerStartX, mRoundCornerStartY;
  private float mRoundCornerEndX, mRoundCornerEndY;

  BorderCorner() {
  }

  final void set(float cornerRadius, float preBorderWidth, float postBorderWidth,
                 @NonNull RectF borderBox, float angleBisector) {
    boolean dirty = !FloatUtil.floatsEqual(mCornerRadius, cornerRadius)
        || !FloatUtil.floatsEqual(mPreBorderWidth, preBorderWidth)
        || !FloatUtil.floatsEqual(mPostBorderWidth, postBorderWidth)
        || !FloatUtil.floatsEqual(mAngleBisector, angleBisector)
        || (null != mBorderBox && mBorderBox.equals(borderBox));

    if (dirty) {
      mCornerRadius = cornerRadius;
      mPreBorderWidth = preBorderWidth;
      mPostBorderWidth = postBorderWidth;
      mBorderBox = borderBox;
      mAngleBisector = angleBisector;

      hasOuterCorner = mCornerRadius > 0 && !FloatUtil.floatsEqual(0, mCornerRadius);

      hasInnerCorner = (hasOuterCorner
          && (getPreBorderWidth() >= 0)
          && (getPostBorderWidth() >= 0)
          && (getOuterCornerRadius() > getPreBorderWidth())
          && (getOuterCornerRadius() > getPostBorderWidth()));

      if (hasOuterCorner) {
        prepareOval();
      }
      prepareRoundCorner();
    }
  }

  /** Build oval data */
  abstract protected void prepareOval();

  /** Build corner data */
  abstract protected void prepareRoundCorner();

  public final void drawRoundedCorner(@NonNull Canvas canvas, @NonNull Paint paint, float startAngle) {
    if (this.hasOuterCorner()) {
      /*Due to the problem of hardware-acceleration, border-radius in some case will not
       be rendered if Path.addArc used instead and the following condition met.
       1. hardware-acceleration enabled
       2. System version is Android 4.1
       3. Screen width is 720px.
       http://dotwe.org/weex/421b9ad09fde51c0b49bb56b37fcf955
      */
      if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
        canvas.drawArc(mOvalLeft, mOvalTop, mOvalRight, mOvalBottom, startAngle, BorderCorner.SWEEP_ANGLE, false,
            paint);
      } else {
        canvas.drawArc(new RectF(mOvalLeft, mOvalTop, mOvalRight, mOvalBottom), startAngle, BorderCorner.SWEEP_ANGLE,
            false, paint);
      }
    } else {
      canvas.drawLine(getRoundCornerStartX(), getRoundCornerStartY(), getRoundCornerEndX(), getRoundCornerEndY(),
          paint);
    }
  }


  public final float getRoundCornerStartX() {
    return mRoundCornerStartX;
  }

  final void setRoundCornerStartX(float roundCornerStartX) {
    this.mRoundCornerStartX = roundCornerStartX;
  }

  public final float getRoundCornerStartY() {
    return mRoundCornerStartY;
  }

  final void setRoundCornerStartY(float roundCornerStartY) {
    this.mRoundCornerStartY = roundCornerStartY;
  }

  public final float getRoundCornerEndX() {
    return mRoundCornerEndX;
  }

  final void setRoundCornerEndX(float mRoundCornerEndX) {
    this.mRoundCornerEndX = mRoundCornerEndX;
  }

  public final float getRoundCornerEndY() {
    return mRoundCornerEndY;
  }

  final void setRoundCornerEndY(float mRoundCornerEndY) {
    this.mRoundCornerEndY = mRoundCornerEndY;
  }

  final void setOvalLeft(float mOvalLeft) {
    this.mOvalLeft = mOvalLeft;
  }

  final void setOvalTop(float mOvalTop) {
    this.mOvalTop = mOvalTop;
  }

  final void setOvalRight(float mOvalRight) {
    this.mOvalRight = mOvalRight;
  }

  final void setOvalBottom(float mOvalBottom) {
    this.mOvalBottom = mOvalBottom;
  }

  /**
   * Tell whether this corner has a rounded inner corner.
   * If a corner has a rounded inner corner, it has an outer corner as well.
   * @return true for a rounded inner corner, otherwise false.
   */
  boolean hasInnerCorner() {
    return hasInnerCorner;
  }

  /**
   * Tell whether this corner has a rounded outer corner.
   * @return true for a rounded outer corner, otherwise false.
   */
  boolean hasOuterCorner() {
    return hasOuterCorner;
  }

  protected final float getPreBorderWidth() {
    return mPreBorderWidth;
  }

  protected final float getPostBorderWidth() {
    return mPostBorderWidth;
  }

  protected final float getOuterCornerRadius() {
    return mCornerRadius;
  }

  protected final float getAngleBisectorDegree(){
    return mAngleBisector;
  }

  protected final RectF getBorderBox() {
    return mBorderBox;
  }

}
