<template>
    <div
        :class="classes()"
        @click="onClick('cell')"
        @touchstart="startDrag"
        @touchmove="onDrag"
        @touchend="endDrag"
        @touchcancel="endDrag"
    >
        <div
            :class="classes('wrapper')"
            :style="wrapperStyle"
            @transitionend="() => { this.swiping = false; }"
        >
            <div v-if="leftWidth" :class="classes('left')" @click="onClick('left', true)">
                <slot name="left"></slot>
            </div>
            <slot></slot>
            <div v-if="rightWidth" :class="classes('right')" @click="onClick('right', true)">
                <slot name="right"></slot>
            </div>
        </div>
    </div>
</template>
<script>
import { TouchMixin } from '../../common/mixins/touch';
import { classesMixin } from '../../common/mixins/classname';
import { ClickOutsideMixin } from '../../common/mixins/click-outside';
import { range } from '../../common/utils/index';
let classMixin = classesMixin('swipe-cell');
const THRESHOLD = 0.15;
export default {
    name: 'h-swipe-cell',
    mixins: [TouchMixin, classMixin, ClickOutsideMixin({
        event: 'touchstart',
        method: 'onClick'
    })],
    props: {
        onClose: Function,
        disabled: Boolean,
        leftWidth: {
            type: Number,
            default: 0
        },
        rightWidth: {
            type: Number,
            default: 0
        }
    },
    data() {
        return {
            offset: 0,
            dragging: false
        };
    },
    computed: {
        wrapperStyle() {
            return {
                transform: `translate3d(${this.offset}px, 0, 0)`,
                transition: this.dragging ? 'none' : '.6s cubic-bezier(0.18, 0.89, 0.32, 1)'
            }
        }
    },
    methods: {
        open(position) {
            const offset = position === 'left' ? this.leftWidth : -this.rightWidth;
            this.swipeMove(offset);
            this.resetSwipeStatus();
        },

        close() {
            this.offset = 0;
        },

        resetSwipeStatus() {
            this.swiping = false;
            this.opened = true;
        },

        swipeMove(offset = 0) {
            this.offset = range(offset, -this.rightWidth, this.leftWidth);
            if (this.offset) {
                this.swiping = true;
            } else {
                this.opened = false;
            }
        },

        swipeLeaveTransition(direction) {
            const { offset, leftWidth, rightWidth } = this;
            const threshold = this.opened ? 1 - THRESHOLD : THRESHOLD;

            // right
            if (direction === 'right' && -offset > rightWidth * threshold && rightWidth > 0) {
                this.open('right');
                // left
            } else if (direction === 'left' && offset > leftWidth * threshold && leftWidth > 0) {
                this.open('left');
                // reset
            } else {
                this.swipeMove(0);
            }
        },

        startDrag(event) {
            if (this.disabled) {
                return;
            }

            this.dragging = true;
            this.startOffset = this.offset;
            this.touchStart(event);
        },

        onDrag(event) {
            if (this.disabled) {
                return;
            }

            this.touchMove(event);

            if (this.direction === 'horizontal') {
                event.preventDefault();
                this.swipeMove(this.deltaX + this.startOffset);
            }
        },

        endDrag() {
            if (this.disabled) {
                return;
            }

            this.dragging = false;
            if (this.swiping) {
                this.swipeLeaveTransition(this.offset > 0 ? 'left' : 'right');
            }
        },

        onClick(position = 'outside', stop) {
            if ( stop ) {

            }
            this.$emit('click', position);

            if (!this.offset) {
                return;
            }

            if (this.onClose) {
                this.onClose(position, this);
            } else {
                this.swipeMove(0);
            }
        }
    }
}
</script>
<style lang="less" scoped>
@import './index.less';
</style>