<template>
  <view
    v-if="inited"
    class="u-transition"
    ref="u-transition"
    @tap="clickHandler"
    :class="classes"
    :style="[mergeStyle]"
    @touchmove="noop"
  >
    <slot />
  </view>
</template>

<script>
import props from './props.js';
// 组件的methods方法，由于内容较长，写在外部文件中通过mixin引入
import transition from './transition.js';
/**
 * transition  动画组件
 * @description
 * @tutorial
 * @property {String}			show			是否展示组件 （默认 false ）
 * @property {String}			mode			使用的动画模式 （默认 'fade' ）
 * @property {String | Number}	duration		动画的执行时间，单位ms （默认 '300' ）
 * @property {String}			timingFunction	使用的动画过渡函数 （默认 'ease-out' ）
 * @property {Object}			customStyle		自定义样式
 * @event {Function} before-enter	进入前触发
 * @event {Function} enter			进入中触发
 * @event {Function} after-enter	进入后触发
 * @event {Function} before-leave	离开前触发
 * @event {Function} leave			离开中触发
 * @event {Function} after-leave	离开后触发
 * @example
 */
export default {
  name: 'k-transition',
  data() {
    return {
      inited: false, // 是否显示/隐藏组件
      // viewStyle: {}, // 组件内部的样式
      status: '', // 记录组件动画的状态
      transitionEnded: false, // 组件是否结束的标记
      // display: false, // 组件是否展示
      classes: '', // 应用的类名
    };
  },
  computed: {
    viewStyle() {
      const style = {};
      const addStyle =
        uni.$k.addStyle(this.width || this.w) &&
        (style.width = addStyle(this.width || this.w))(this.height || this.h) &&
        (style.height = addStyle(this.height || this.h))(
          this.margin || this.m
        ) &&
        (style.margin = addStyle(this.margin || this.m))(
          this.marginTop || this.mt
        ) &&
        (style.marginTop = addStyle(this.marginTop || this.mt))(
          this.marginRight || this.mr
        ) &&
        (style.marginRight = addStyle(this.marginRight || this.mr))(
          this.marginBottom || this.mb
        ) &&
        (style.marginBottom = addStyle(this.marginBottom || this.mb))(
          this.marginLeft || this.ml
        ) &&
        (style.marginLeft = addStyle(this.marginLeft || this.ml))(
          this.padding || this.p
        ) &&
        (style.padding = addStyle(this.padding || this.p))(
          this.paddingTop || this.pt
        ) &&
        (style.paddingTop = addStyle(this.paddingTop || this.pt))(
          this.paddingRight || this.pr
        ) &&
        (style.paddingRight = addStyle(this.paddingRight || this.pr))(
          this.paddingBottom || this.pb
        ) &&
        (style.paddingBottom = addStyle(this.paddingBottom || this.pb))(
          this.paddingLeft || this.pl
        ) &&
        (style.paddingLeft = addStyle(this.paddingLeft || this.pl))(
          this.color || this.c
        ) &&
        (style.color = this.color || this.c)(this.fontSize || this.fs) &&
        (style.fontSize = this.fontSize || this.fs)(
          this.borderRadius || this.radius
        ) &&
        (style.borderRadius = this.borderRadius || this.radius)(
          this.position || this.pos
        ) &&
        this.position(this.flexDirection || this.fd) &&
        this.flexDirection(this.justifyContent || jc) &&
        this.justifyContent(this.alignItems || ai) &&
        this.alignItems;

      return uni.$k.deepMerge(style, uni.$k.addStyle(this.customStyle));
    },
    mergeStyle() {
      const { viewStyle, customStyle } = this;
      return {
        // #ifndef APP-NVUE
        transitionDuration: `${this.duration}ms`,
        // display: `${this.display ? '' : 'none'}`,
        transitionTimingFunction: this.timingFunction,
        // #endif
        // 避免自定义样式影响到动画属性，所以写在viewStyle前面
        ...uni.$k.addStyle(customStyle),
        ...viewStyle,
      };
    },
  },
  // 将mixin挂在到组件中，uni.$k.mixin实际上为一个vue格式对象
  mixins: [uni.$k.mpMixin, uni.$k.mixin, transition, props],
  watch: {
    show: {
      handler(newVal) {
        // vue和nvue分别执行不同的方法
        // #ifdef APP-NVUE
        newVal ? this.nvueEnter() : this.nvueLeave();
        // #endif
        // #ifndef APP-NVUE
        newVal ? this.vueEnter() : this.vueLeave();
        // #endif
      },
      // 表示同时监听初始化时的props的show的意思
      immediate: true,
    },
  },
  methods: {
    // 阻止事件冒泡
    preventEvent(e) {
      e && typeof e.stopPropagation === 'function' && e.stopPropagation();
    },
    // 空操作
    noop(e) {
      this.preventEvent(e);
    },
  },
};
</script>

<style lang="scss" scoped>
@import "../../config/css/components";
/* #ifndef APP-NVUE */
// vue版本动画相关的样式抽离在外部文件
@import "./ani-style";
/* #endif */
</style>
