/*
 * 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.utils;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.os.Build;
import android.os.Build.VERSION_CODES;
import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import com.taobao.weex.WXEnvironment;
import com.taobao.weex.WXSDKInstance;
import com.taobao.weex.WXSDKManager;
import com.taobao.weex.common.Constants;
import com.taobao.weex.common.WXRuntimeException;
import com.taobao.weex.ui.flat.widget.Widget;
import com.taobao.weex.ui.flat.widget.WidgetGroup;
import com.taobao.weex.ui.view.border.BorderDrawable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Utility class for views
 */
public class WXViewUtils {

  @IntDef({PixelFormat.TRANSLUCENT, PixelFormat.TRANSPARENT, PixelFormat.OPAQUE})
  @Retention(RetentionPolicy.SOURCE)
  public @interface Opacity {}

  /**
   * Use {@link PixelFormat#TRANSLUCENT} instead
   */
  @Deprecated
  public static final int TRANSLUCENT = PixelFormat.TRANSLUCENT;

  /**
   * Use {@link PixelFormat#TRANSPARENT} instead.
   */
  @Deprecated
  public static final int TRANSPARENT = PixelFormat.TRANSPARENT;

  /**
   * Use {@link PixelFormat#OPAQUE} instead
   */
  @Deprecated
  public static final int OPAQUE = PixelFormat.OPAQUE;

  public static final int DIMENSION_UNSET = -1;
  private static final boolean mUseWebPx = false;

  private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);

  @SuppressLint("NewApi")
  public static int generateViewId() {

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
      for (;;) {
        final int result = sNextGeneratedId.get();
        // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
        int newValue = result + 1;
        if (newValue > 0x00FFFFFF)
          newValue = 1; // Roll over to 1, not 0.
        if (sNextGeneratedId.compareAndSet(result, newValue)) {
          return result;
        }
      }
    } else {
      return View.generateViewId();
    }
  }

  private static int mScreenWidth;
  private static int mScreenHeight;


  public static int getWeexHeight(String instanceId){
    WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
    if (instance != null) {
      int weexHeight = instance.getWeexHeight();
      if (weexHeight >= 0 || weexHeight == -2) {
        return weexHeight;
      }
      else {
        return getScreenHeight(WXEnvironment.sApplication);
      }
    }
    return -3;
  }



  public static int getWeexWidth(String instanceId){
    WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
    if (instance != null) {
      int weexWidth = instance.getWeexWidth();
      if (weexWidth >= 0 || weexWidth == -2) {
        return weexWidth;
      }
      else {
        return getScreenWidth(WXEnvironment.sApplication);
      }
    }
    return -3;
  }

  @Deprecated
  public static int getScreenWidth( ) {
    return getScreenWidth(WXEnvironment.sApplication);
  }

  @Deprecated
  public static int setScreenWidth(int screenWidth) {
    return mScreenWidth = screenWidth;
  }

  public static float getScreenDensity(Context ctx){
    if(ctx != null){
      try{
        Resources res = ctx.getResources();
        return res.getDisplayMetrics().density;
      }catch (Exception e){
        WXLogUtils.e("getScreenDensityDpi exception:"+e.getMessage());
      }
    }
    return Constants.Value.DENSITY;
  }

  public static int getScreenWidth(Context ctx) {
    if(ctx!=null){
      Resources res = ctx.getResources();
      mScreenWidth = res.getDisplayMetrics().widthPixels;
      if(WXEnvironment.SETTING_FORCE_VERTICAL_SCREEN){
        mScreenHeight = res
                .getDisplayMetrics()
                .heightPixels;
        mScreenWidth = mScreenHeight > mScreenWidth ? mScreenWidth : mScreenHeight;
      }
    } else if(WXEnvironment.isApkDebugable()){
      throw new WXRuntimeException("Error Context is null When getScreenHeight");
    }
    return mScreenWidth;
  }


  @Deprecated
  public static int getScreenHeight() {
    return getScreenHeight(WXEnvironment.sApplication);
  }

  public static int getScreenHeight(Context cxt) {
    if(cxt!=null){
      Resources res = cxt.getResources();
      mScreenHeight =cxt.getResources().getDisplayMetrics().heightPixels;
      if(WXEnvironment.SETTING_FORCE_VERTICAL_SCREEN){
        mScreenWidth = res
                .getDisplayMetrics()
                .widthPixels;
        mScreenHeight = mScreenHeight > mScreenWidth ? mScreenHeight : mScreenWidth;
      }
    } else if (WXEnvironment.isApkDebugable()){
      throw new WXRuntimeException("Error Context is null When getScreenHeight");
    }
    return mScreenHeight;
  }

  /**
   * Convert distance from JS,CSS to native. As the JS considers the width of the screen is 750px.
   * There must be a transform when accessing distance from JS,CSS and use it.
   * Basically, this method calculates a scale factor(ScreenWidth/750) and use apply this scale
   * factor to JS,CSS distance.
   * @param pxValue the raw distance from JS or CSS. The result will be rounded to a closet int.
   * @return the actual distance in the screen.
   */

  @Deprecated
  public static float getRealPxByWidth(float pxValue) {
    return getRealPxByWidth(pxValue,750);
  }
  public static float getRealPxByWidth(float pxValue,int customViewport) {
    if (Float.isNaN(pxValue)) {
      return pxValue;
    }
    if (mUseWebPx) {
      return (float) Math.rint(pxValue);
    } else {
      float realPx = (pxValue * getScreenWidth() / customViewport);
      return realPx > 0.005 && realPx < 1 ? 1 : (float) Math.rint(realPx);
    }
  }

  @Deprecated
  public static float getRealSubPxByWidth(float pxValue) {
    return getRealSubPxByWidth(pxValue,750);
  }

  public static float getRealSubPxByWidth(float pxValue,int customViewport) {
    if (Float.isNaN(pxValue)) {
      return pxValue;
    }
    if (mUseWebPx) {
      return (float) Math.rint(pxValue);
    } else {
      float realPx = (pxValue * getScreenWidth() / customViewport);
      return realPx > 0.005 && realPx < 1 ? 1 : realPx;
    }
  }

  /**
   *  Internal interface that just for debug, you should never call this method because of accuracy loss obviously
   */
  @Deprecated
  public static float getWeexPxByReal(float pxValue) {
    return getWeexPxByReal(pxValue,750);
  }

  public static float getWeexPxByReal(float pxValue,int customViewport) {
    if (Float.isNaN(pxValue)) {
      return pxValue;
    }
    if (mUseWebPx) {
      return (float) Math.rint(pxValue);
    } else {
      return pxValue * customViewport / getScreenWidth();
    }
  }

  @Deprecated
  public static float getRealPxByWidth2(float pxValue) {
    return getRealPxByWidth2(pxValue,750);
  }
  public static int getRealPxByWidth2(float pxValue,int customViewport) {
    if (mUseWebPx) {
      return (int) pxValue;
    } else {
      float realPx = (pxValue * getScreenWidth() / customViewport);
      return realPx > 0.005 && realPx < 1 ? 1 : (int) realPx - 1;
    }
  }

  /**
   * Convert distance from native to JS,CSS. As the JS considers the width of the screen is 750px.
   * There must be a transform when return distance to JS,CSS.
   * Basically, this method calculates a scale factor(ScreenWidth/750) and use apply this scale
   * factor to native distance.
   * @param pxValue the raw distance of native. The result will be rounded to a closet int.
   * @return the distance in JS,CSS where the screenWidth is 750 px.
   */
  @Deprecated
  public static float getWebPxByWidth(float pxValue) {
    return getWebPxByWidth(pxValue,750);
  }

  public static float getWebPxByWidth(float pxValue,int customViewport) {
    if (pxValue < -1.9999 && pxValue > -2.005) {
      return Float.NaN;
    }
    if (mUseWebPx) {
      return pxValue;
    } else {
      float realPx = (pxValue * customViewport / getScreenWidth());
      return realPx > 0.005 && realPx < 1 ? 1 : realPx;
    }
  }


  /**
   * Convert dp to px
   * @param dpValue the dp value to be converted
   * @return the px value
   */
  public static int dip2px(float dpValue) {
    float scale = 2;
    try {
      scale = WXEnvironment.getApplication().getResources()
              .getDisplayMetrics().density;
    } catch (Exception e) {
      WXLogUtils.e("[WXViewUtils] dip2px:", e);
    }
    float finalPx = (dpValue * scale + 0.5f);
    return finalPx > 0 && finalPx < 1 ? 1 : (int) finalPx;
  }

  public static boolean onScreenArea(View view) {
    if (view == null || view.getVisibility() != View.VISIBLE) {
      return false;
    }

    int[] p = new int[2];
    view.getLocationOnScreen(p);
    LayoutParams lp = view.getLayoutParams();
    int viewH = 0;
    if (lp != null) {
      viewH = lp.height;
    } else {
      viewH = view.getHeight();
    }

    return (p[1] > 0 && (p[1] - WXViewUtils.getScreenHeight(WXEnvironment.sApplication) < 0))
            || (viewH + p[1] > 0 && p[1] <= 0);
  }

  /**
   * Multiplies the color with the given alpha.
   *
   * @param color color to be multiplied
   * @param alpha value between 0 and 255
   * @return multiplied color
   */
  public static int multiplyColorAlpha(int color, int alpha) {
    if (alpha == 255) {
      return color;
    }
    if (alpha == 0) {
      return color & 0x00FFFFFF;
    }
    alpha = alpha + (alpha >> 7); // make it 0..256
    int colorAlpha = color >>> 24;
    int multipliedAlpha = colorAlpha * alpha >> 8;
    return (multipliedAlpha << 24) | (color & 0x00FFFFFF);
  }

  @Opacity
  public static int getOpacityFromColor(int color) {
    int colorAlpha = color >>> 24;
    if (colorAlpha == 255) {
      return PixelFormat.OPAQUE;
    } else if (colorAlpha == 0) {
      return PixelFormat.TRANSPARENT;
    } else {
      return PixelFormat.TRANSLUCENT;
    }
  }

  @SuppressWarnings("deprecation")
  public static void setBackGround(View view, Drawable drawable){
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN){
      view.setBackgroundDrawable(drawable);
    }
    else{
      view.setBackground(drawable);
    }
  }

  public static @Nullable
  BorderDrawable getBorderDrawable(@NonNull View view){
    Drawable drawable=view.getBackground();
    if(drawable instanceof BorderDrawable){
      return (BorderDrawable) drawable;
    }
    else if(drawable instanceof LayerDrawable){
      if(((LayerDrawable) drawable).getNumberOfLayers()>1) {
        Drawable innerDrawable=((LayerDrawable) drawable).getDrawable(0);
        if(innerDrawable instanceof BorderDrawable){
          return (BorderDrawable) innerDrawable;
        }
      }
    }
    return null;
  }

  public static void clipCanvasWithinBorderBox(View targetView, Canvas canvas) {
    Drawable drawable;
    if (clipCanvasDueToAndroidVersion(canvas) &&
            clipCanvasIfAnimationExist(targetView) &&
            ((drawable = targetView.getBackground()) instanceof BorderDrawable)) {
      BorderDrawable borderDrawable = (BorderDrawable) drawable;
      if (borderDrawable.isRounded()) {
        if (clipCanvasIfBackgroundImageExist(targetView, borderDrawable)) {
          Path path = borderDrawable.getContentPath(
                  new RectF(0, 0, targetView.getWidth(), targetView.getHeight()));
          canvas.clipPath(path);
        }
      }
    }
  }

  public static void clipCanvasWithinBorderBox(Widget widget, Canvas canvas) {
    BorderDrawable borderDrawable;
    if (clipCanvasDueToAndroidVersion(canvas) &&
            clipCanvasIfAnimationExist(null) &&
            (borderDrawable=widget.getBackgroundAndBorder())!=null ) {
      if (borderDrawable.isRounded() && clipCanvasIfBackgroundImageExist(widget, borderDrawable)) {
        Path path = borderDrawable.getContentPath(
                new RectF(0, 0, widget.getBorderBox().width(), widget.getBorderBox().height()));
        canvas.clipPath(path);
      }
      else {
        canvas.clipRect(widget.getBorderBox());
      }
    }
  }

  /**
   * According to https://developer.android.com/guide/topics/graphics/hardware-accel.html#unsupported
   API 18 or higher supports clipPath to canvas based on hardware acceleration.
   * @param canvas
   * @return
   */
  private static boolean clipCanvasDueToAndroidVersion(Canvas canvas) {
    return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2 ||
            !canvas.isHardwareAccelerated();
  }

  /**
   * According to https://code.google.com/p/android/issues/detail?id=225556&sort=-id&colspec=ID
   * clipPath doesn't work with rotation nor scale when API level is 24.
   * As animation will not cause redraw if hardware-acceleration enabled, clipCanvas feature has
   * to be disabled when API level is 24 without considering the animation property.
   */
  private static boolean clipCanvasIfAnimationExist(View targetView) {
    if (Build.VERSION.SDK_INT != VERSION_CODES.N) {
      return true;
    } else {
      return false;
    }
  }

  /**
   * Due limitation in Android platform, the linear gradient in the following page will not be
   * rounded if {@link Canvas#clipPath(Path)} of the parent view invoked when API level is lower
   * than 21.
   * http://dotwe.org/weex/963c9ade129f86757cecdd85651cd30e
   * @param targetView
   * @param borderDrawable
   * @return
   */
  private static boolean clipCanvasIfBackgroundImageExist(@NonNull View targetView,
                                                          @NonNull BorderDrawable borderDrawable) {
    if (targetView instanceof ViewGroup) {
      View child;
      ViewGroup parent = ((ViewGroup) targetView);
      int count = parent.getChildCount();
      for (int i = 0; i < count; i++) {
        child = parent.getChildAt(i);
        if (child.getBackground() instanceof BorderDrawable &&
                ((BorderDrawable) child.getBackground()).hasImage() &&
                Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
          return false;
        }
      }
    }
    return true;
  }

  private static boolean clipCanvasIfBackgroundImageExist(@NonNull Widget widget,
                                                          @NonNull BorderDrawable borderDrawable) {
    if (widget instanceof WidgetGroup) {
      for (Widget child : ((WidgetGroup) widget).getChildren()) {
        if (child.getBackgroundAndBorder().hasImage() &&
                Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
          return false;
        }
      }
    }
    return true;
  }
}
