content: /*
   * Created by LuaView.
   * Copyright (c) 2017, Alibaba Group. All rights reserved.
   *
   * This source code is licensed under the MIT.
   * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree.
   */
  
  package com.taobao.luaview.userdata.ui;
  
  import android.animation.Animator;
  import android.animation.ObjectAnimator;
  import android.animation.PropertyValuesHolder;
  import android.animation.ValueAnimator;
  import android.os.Build;
  import android.text.TextUtils;
  import android.view.animation.Interpolator;
  
  import com.taobao.luaview.userdata.base.BaseUserdata;
  import com.taobao.luaview.util.AnimatorUtil;
  import com.taobao.luaview.util.LuaUtil;
  
  import org.luaj.vm2.Globals;
  import org.luaj.vm2.LuaTable;
  import org.luaj.vm2.LuaValue;
  import org.luaj.vm2.Varargs;
  
  import java.util.Arrays;
  import java.util.List;
  
  /**
   * Animator 数据封装
   *
   * @author song
   */
  public class UDAnimator extends BaseUserdata {
      private LuaValue mOnStartCallback;
      private LuaValue mOnEndCallback;
      private LuaValue mOnCancelCallback;
      private LuaValue mOnRepeatCallback;
      private LuaValue mOnPauseCallback;
      private LuaValue mOnResumeCallback;
      private LuaValue mOnUpdateCallback;
  
      private Boolean isRunning;
  
      private UDView mTarget;
  
  
      public UDAnimator(Globals globals, LuaValue metaTable, Varargs varargs) {
          super(new ObjectAnimator(), globals, metaTable, varargs);
          init();
      }
  
      private ObjectAnimator getAnimator() {
          return (ObjectAnimator) userdata();
      }
  
      private void init() {
          final ObjectAnimator animator = getAnimator();
          if (animator != null) {
              if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
                  animator.setAutoCancel(true);
              }
          }
      }
  
      /**
       * 设置target
       *
       * @param udView
       * @return
       */
      public UDAnimator with(UDView udView) {
          final ObjectAnimator animator = getAnimator();
          if (animator != null && udView != null && udView.getView() != null) {
              mTarget = udView;
              animator.setTarget(udView.getView());
          }
          return this;
      }
  
      public UDAnimator setCallback(LuaTable callbacks) {
          if (callbacks != null) {
              mOnStartCallback = LuaUtil.getFunction(callbacks, "onStart", "OnStart");
              mOnEndCallback = LuaUtil.getFunction(callbacks, "onEnd", "OnEnd");
              mOnCancelCallback = LuaUtil.getFunction(callbacks, "onCancel", "OnCancel");
              mOnPauseCallback = LuaUtil.getFunction(callbacks, "onPause", "OnPause");
              mOnResumeCallback = LuaUtil.getFunction(callbacks, "onResume", "OnResume");
              mOnRepeatCallback = LuaUtil.getFunction(callbacks, "onRepeat", "OnRepeat");
              mOnUpdateCallback = LuaUtil.getFunction(callbacks, "onUpdate", "OnUpdate");
          }
          return this;
      }
  
      public UDAnimator setOnStartCallback(LuaValue mOnStartCallback) {
          this.mOnStartCallback = mOnStartCallback;
          return this;
      }
  
      public UDAnimator setOnEndCallback(LuaValue mOnEndCallback) {
          this.mOnEndCallback = mOnEndCallback;
          return this;
      }
  
      public UDAnimator setOnCancelCallback(LuaValue mOnCancelCallback) {
          this.mOnCancelCallback = mOnCancelCallback;
          return this;
      }
  
      public UDAnimator setOnRepeatCallback(LuaValue mOnRepeatCallback) {
          this.mOnRepeatCallback = mOnRepeatCallback;
          return this;
      }
  
      public UDAnimator setOnPauseCallback(LuaValue mOnPauseCallback) {
          this.mOnPauseCallback = mOnPauseCallback;
          return this;
      }
  
      public UDAnimator setOnResumeCallback(LuaValue mOnResumeCallback) {
          this.mOnResumeCallback = mOnResumeCallback;
          return this;
      }
  
      public UDAnimator setOnUpdateCallback(LuaValue mOnUpdateCallback) {
          this.mOnUpdateCallback = mOnUpdateCallback;
          return this;
      }
  
  
      /**
       * 设置属性
       *
       * @param name
       * @return
       */
      public UDAnimator ofProperty(final String name, float... values) {
          final ObjectAnimator animator = getAnimator();
          if (animator != null && TextUtils.isEmpty(name) == false && values != null) {
              PropertyValuesHolder[] valuesHolders = null;
              if (animator.getValues() != null && animator.getValues().length > 0) {
                  valuesHolders = Arrays.copyOf(animator.getValues(), animator.getValues().length + 1);
              } else {
                  valuesHolders = new PropertyValuesHolder[1];
              }
              valuesHolders[valuesHolders.length - 1] = PropertyValuesHolder.ofFloat(name, values);
              animator.setValues(valuesHolders);
          }
          return this;
      }
  
      /**
       * 时长
       *
       * @param duration
       * @return
       */
      public UDAnimator setDuration(long duration) {
          final ObjectAnimator animator = getAnimator();
          if (animator != null && duration >= 0) {
              animator.setDuration(duration);
          }
          return this;
      }
  
      /**
       * 启动延时
       *
       * @param delay
       * @return
       */
      public UDAnimator setStartDelay(long delay) {
          final ObjectAnimator animator = getAnimator();
          if (animator != null && delay >= 0) {
              animator.setStartDelay(delay);
          }
          return this;
      }
  
      /**
       * 重复次数，负数标示无限
       *
       * @param repeatCount
       * @return
       */
      public UDAnimator setRepeatCount(int repeatCount) {
          final ObjectAnimator animator = getAnimator();
          if (animator != null) {
              if (repeatCount >= 0) {
                  animator.setRepeatCount(repeatCount);
              } else {
                  animator.setRepeatCount(ValueAnimator.INFINITE);
              }
          }
          return this;
      }
  
      /**
       * 重复方式(1 default, -1 infinite, 2 reverse)
       *
       * @param repeatMode
       * @return
       */
      public UDAnimator setRepeatMode(int repeatMode) {
          final ObjectAnimator animator = getAnimator();
          if (animator != null) {
              animator.setRepeatMode(repeatMode);
          }
          return this;
      }
  
      /**
       * 浮点数
       *
       * @param values
       * @return
       */
      public UDAnimator setFloatValues(float... values) {
          final ObjectAnimator animator = getAnimator();
          if (animator != null && values != null && values.length > 0) {
              animator.setFloatValues(values);
          }
          return this;
      }
  
      /**
       * 整数
       *
       * @param values
       * @return
       */
      public UDAnimator setIntValues(int... values) {
          final ObjectAnimator animator = getAnimator();
          if (animator != null && values != null && values.length > 0) {
              animator.setIntValues(values);
          }
          return this;
      }
  
      /**
       * 加速器
       * AccelerateDecelerateInterpolator,
       * AccelerateInterpolator,
       * AnticipateInterpolator,
       * AnticipateOvershootInterpolator,
       * BaseInterpolator,
       * BounceInterpolator,
       * CycleInterpolator,
       * DecelerateInterpolator,
       * FastOutLinearInInterpolator,
       * FastOutSlowInInterpolator,
       * LinearInterpolator,
       * LinearOutSlowInInterpolator,
       * OvershootInterpolator,
       * PathInterpolator
       *
       * @param interpolator
       * @return
       */
      public UDAnimator setInterpolator(final Interpolator interpolator) {
          final ObjectAnimator animator = getAnimator();
          if (animator != null && interpolator != null) {
              animator.setInterpolator(interpolator);
          }
          return this;
      }
  
      /**
       * start all animator
       *
       * @return
       */
      public UDAnimator start() {
          final ObjectAnimator animator = getAnimator();
          setupListeners(animator);
          AnimatorUtil.start(animator);
          if (mTarget != null) {
              mTarget.startAnimation();
          }
          return this;
      }
  
      /**
       * cancel animator
       *
       * @return
       */
      public UDAnimator cancel() {
          AnimatorUtil.cancel(getAnimator());
          if (mTarget != null) {
              mTarget.cancelAnimation();
          }
          return this;
      }
  
      /**
       * pause animator
       *
       * @return
       */
      public UDAnimator pause() {
          AnimatorUtil.pause(getAnimator());
          if (mTarget != null) {
              mTarget.pauseAnimation();
          }
          return this;
      }
  
      /**
       * resume animator
       *
       * @return
       */
      public UDAnimator resume() {
          AnimatorUtil.resume(getAnimator());
          if (mTarget != null) {
              mTarget.resumeAnimation();
          }
          return this;
      }
  
      /**
       * end animator
       *
       * @return
       */
      public UDAnimator end() {
          AnimatorUtil.end(getAnimator());
          if (mTarget != null) {
              mTarget.endAnimation();
          }
          return this;
      }
  
      /**
       * is paused
       *
       * @return
       */
      public boolean isPaused() {
          return AnimatorUtil.isPaused(getAnimator()) || (mTarget != null && mTarget.isAnimationPaused());
      }
  
      /**
       * is running
       * TODO 这里的判断有问题
       * @return
       */
      public boolean isRunning() {
          if (isRunning != null) {
              return isRunning;
          }
          return AnimatorUtil.isRunning(getAnimator()) || (mTarget != null && mTarget.isAnimating());
      }
  
      /**
       * setup listeners
       *
       * @param animator
       * @return
       */
      public UDAnimator setupListeners(ObjectAnimator animator) {
          if (animator != null) {
              animator.removeAllListeners();//删除所有listener, pause listener
              animator.removeAllUpdateListeners();//删除所有update listener
              addAnimatorListener(animator);
              addOnPauseListener(animator);
              addOnUpdateListener(animator);
          }
          return this;
      }
  
      /**
       * build a copy of given animator
       *
       * @return
       */
      public Animator build() {
          //这种方式clone出来的animator不能重复播放
          /*final ObjectAnimator result = getAnimator().clone();//克隆一份
          setupListeners(result);
          result.setupStartValues();
          return result;*/
  
          final ObjectAnimator self = this.getAnimator();
          final ObjectAnimator anim = new ObjectAnimator();
          anim.setTarget(self.getTarget());
          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
              anim.setAutoCancel(true);
          }
          if (self.getValues() != null) {
              anim.setValues(self.getValues());
          }
          anim.setInterpolator(self.getInterpolator());
          anim.setDuration(self.getDuration());
          anim.setStartDelay(self.getStartDelay());
          anim.setRepeatCount(self.getRepeatCount());
          anim.setRepeatMode(self.getRepeatMode());
          setupListeners(anim);
          return anim;
      }
  
      public List<PropertyValuesHolder> getPropertyValuesHolder() {
          return Arrays.asList(getAnimator().getValues());
      }
      //----------------------------------------listeners---------------------------------------------
  
      private void addAnimatorListener(ObjectAnimator animator) {
          if (animator != null && (mOnStartCallback != null || mOnEndCallback != null || mOnCancelCallback != null || mOnRepeatCallback != null)) {
              animator.addListener(new Animator.AnimatorListener() {//add a listener
                  @Override
                  public void onAnimationStart(Animator animation) {
                      isRunning = true;
                      LuaUtil.callFunction(mOnStartCallback);
                  }
  
                  @Override
                  public void onAnimationEnd(Animator animation) {
                      isRunning = false;
                      LuaUtil.callFunction(mOnEndCallback);
                  }
  
                  @Override
                  public void onAnimationCancel(Animator animation) {
                      isRunning = false;
                      LuaUtil.callFunction(mOnCancelCallback);
                  }
  
                  @Override
                  public void onAnimationRepeat(Animator animation) {
                      LuaUtil.callFunction(mOnRepeatCallback);
                  }
              });
          }
      }
  
      private void addOnPauseListener(ObjectAnimator animator) {
          if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
              if (animator != null && (mOnPauseCallback != null || mOnResumeCallback != null)) {
                  animator.addPauseListener(new Animator.AnimatorPauseListener() {
                      @Override
                      public void onAnimationPause(Animator animation) {
                          LuaUtil.callFunction(mOnPauseCallback);
                      }
  
                      @Override
                      public void onAnimationResume(Animator animation) {
                          LuaUtil.callFunction(mOnResumeCallback);
                      }
                  });
              }
          }
      }
  
      private void addOnUpdateListener(ObjectAnimator animator) {
          if (animator != null && mOnUpdateCallback != null) {
              animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                  @Override
                  public void onAnimationUpdate(ValueAnimator animation) {
                      LuaUtil.callFunction(mOnUpdateCallback);
                  }
              });
          }
      }
  }
  