'use strict';

Object.defineProperty(exports, "__esModule", {
    value: true
});

var _deepClone = require('../_utils/deep-clone');

var _commonUtil = require('../utils/commonUtil');

var _numberUtil = require('../utils/numberUtil');

var _event = require('../_utils/dom/event');

var _touch = require('../mixins/touch');

var _mouse = require('../mixins/mouse');

var DEFAULT_DURATION = 200;

// 惯性滑动思路:
// 在手指离开屏幕时，如果和上一次 move 时的间隔小于 `MOMENTUM_LIMIT_TIME` 且 move
// 距离大于 `MOMENTUM_LIMIT_DISTANCE` 时，执行惯性滑动
var MOMENTUM_LIMIT_TIME = 300;
var MOMENTUM_LIMIT_DISTANCE = 15;

function getElementTranslateY(element) {
    var style = window.getComputedStyle(element);
    var transform = style.transform || style.webkitTransform;
    var translateY = transform.slice(7, transform.length - 1).split(', ')[5];

    return Number(translateY);
}

function isOptionDisabled(option) {
    return (0, _commonUtil.isObj)(option) && option.disabled;
}

var pickerViewColumn = {
    mixins: [_touch.TouchMixin, _mouse.MouseMixin],

    props: {
        valueKey: String,
        allowHtml: Boolean,
        className: String,
        itemHeight: Number,
        defaultIndex: Number,
        swipeDuration: Number,
        visibleItemCount: Number,
        initialOptions: {
            type: Array,
            'default': function _default() {
                return [];
            }
        }
    },

    data: function data() {
        return {
            offset: 0,
            duration: 0,
            options: (0, _deepClone.deepClone)(this.initialOptions),
            currentIndex: this.defaultIndex
        };
    },
    created: function created() {
        if (this.$parent.children) {
            this.$parent.children.push(this);
        }

        this.setIndex(this.currentIndex);
    },
    destroyed: function destroyed() {
        var children = this.$parent.children;


        if (children) {
            children.splice(children.indexOf(this), 1);
        }
    },


    watch: {
        defaultIndex: function defaultIndex() {
            this.setIndex(this.defaultIndex);
        }
    },

    computed: {
        count: function count() {
            return this.options.length;
        },
        baseOffset: function baseOffset() {
            return this.itemHeight * (this.visibleItemCount - 1) / 2;
        }
    },

    methods: {
        onTouchStart: function onTouchStart(event) {
            this.touchStart(event);

            if (this.moving) {
                var translateY = getElementTranslateY(this.$refs.wrapper);
                this.offset = Math.min(0, translateY - this.baseOffset);
                this.startOffset = this.offset;
            } else {
                this.startOffset = this.offset;
            }

            this.duration = 0;
            this.transitionEndTrigger = null;
            this.touchStartTime = Date.now();
            this.momentumOffset = this.startOffset;
        },
        onMouseStart: function onMouseStart(event) {
            this.dragging = true;
            this.mouseStart(event);

            if (this.moving) {
                var translateY = getElementTranslateY(this.$refs.wrapper);
                this.offset = Math.min(0, translateY - this.baseOffset);
                this.startOffset = this.offset;
            } else {
                this.startOffset = this.offset;
            }

            this.duration = 0;
            this.transitionEndTrigger = null;
            this.touchStartTime = Date.now();
            this.momentumOffset = this.startOffset;
        },
        onTouchMove: function onTouchMove(event) {
            this.moving = true;
            this.touchMove(event);

            if (this.direction === 'vertical') {
                (0, _event.preventDefault)(event, true);
            }

            this.offset = (0, _numberUtil.range)(this.startOffset + this.deltaY, -(this.count * this.itemHeight), this.itemHeight);

            var now = Date.now();
            if (now - this.touchStartTime > MOMENTUM_LIMIT_TIME) {
                this.touchStartTime = now;
                this.momentumOffset = this.offset;
            }
        },
        onMouseMove: function onMouseMove(event) {
            if (!this.dragging) return;
            this.moving = true;
            this.mouseMove(event);

            if (this.direction === 'vertical') {
                (0, _event.preventDefault)(event, true);
            }

            this.offset = (0, _numberUtil.range)(this.startOffset + this.deltaY, -(this.count * this.itemHeight), this.itemHeight);

            var now = Date.now();
            if (now - this.touchStartTime > MOMENTUM_LIMIT_TIME) {
                this.touchStartTime = now;
                this.momentumOffset = this.offset;
            }
        },
        onTouchEnd: function onTouchEnd() {
            var distance = this.offset - this.momentumOffset;
            var duration = Date.now() - this.touchStartTime;
            var allowMomentum = duration < MOMENTUM_LIMIT_TIME && Math.abs(distance) > MOMENTUM_LIMIT_DISTANCE;

            if (allowMomentum) {
                this.momentum(distance, duration);
                return;
            }

            var index = this.getIndexByOffset(this.offset);
            this.moving = false;
            this.duration = DEFAULT_DURATION;
            this.setIndex(index, true);
        },
        onMouseEnd: function onMouseEnd() {
            if (!this.dragging) return;
            this.dragging = false;
            var distance = this.offset - this.momentumOffset;
            var duration = Date.now() - this.touchStartTime;
            var allowMomentum = duration < MOMENTUM_LIMIT_TIME && Math.abs(distance) > MOMENTUM_LIMIT_DISTANCE;

            if (allowMomentum) {
                this.momentum(distance, duration);
                return;
            }

            var index = this.getIndexByOffset(this.offset);
            this.moving = false;
            this.duration = DEFAULT_DURATION;
            this.setIndex(index, true);
        },
        onMouseWheel: function onMouseWheel(event) {
            (0, _event.preventDefault)(event, true);
            var wheelDelta = event.wheelDelta;
            var nextIndicator = wheelDelta < 0 ? this.currentIndex + 1 : this.currentIndex - 1;
            if (nextIndicator >= 0 && nextIndicator <= this.count) {
                this.setIndex(nextIndicator, true);
            }
        },
        onTransitionEnd: function onTransitionEnd() {
            this.stopMomentum();
        },
        onClickItem: function onClickItem(index) {
            if (this.moving) {
                return;
            }

            this.duration = DEFAULT_DURATION;
            this.setIndex(index, true);
        },
        adjustIndex: function adjustIndex(index) {
            index = (0, _numberUtil.range)(index, 0, this.count);

            for (var i = index; i < this.count; i++) {
                if (!isOptionDisabled(this.options[i])) return i;
            }

            for (var _i = index - 1; _i >= 0; _i--) {
                if (!isOptionDisabled(this.options[_i])) return _i;
            }
        },
        getOptionText: function getOptionText(option) {
            return (0, _commonUtil.isObj)(option) && this.valueKey in option ? option[this.valueKey] : option;
        },
        setIndex: function setIndex(index, userAction) {
            var _this = this;

            index = this.adjustIndex(index) || 0;
            this.offset = -index * this.itemHeight;

            var trigger = function trigger() {
                if (index !== _this.currentIndex) {
                    _this.currentIndex = index;

                    if (userAction) {
                        _this.$emit('change', index);
                    }
                }
            };

            // 若有触发过 `touchmove` 事件，那应该
            // 在 `transitionend` 后再触发 `change` 事件
            if (this.moving) {
                this.transitionEndTrigger = trigger;
            } else {
                trigger();
            }
        },
        setValue: function setValue(value) {
            var options = this.options;

            for (var i = 0; i < options.length; i++) {
                if (this.getOptionText(options[i]) === value) {
                    return this.setIndex(i);
                }
            }
        },
        getValue: function getValue() {
            return this.options[this.currentIndex];
        },
        getIndexByOffset: function getIndexByOffset(offset) {
            return (0, _numberUtil.range)(Math.round(-offset / this.itemHeight), 0, this.count - 1);
        },
        momentum: function momentum(distance, duration) {
            var speed = Math.abs(distance / duration);

            distance = this.offset + speed / 0.002 * (distance < 0 ? -1 : 1);

            var index = this.getIndexByOffset(distance);

            this.duration = this.swipeDuration;
            this.setIndex(index, true);
        },
        stopMomentum: function stopMomentum() {
            this.moving = false;
            this.duration = 0;

            if (this.transitionEndTrigger) {
                this.transitionEndTrigger();
                this.transitionEndTrigger = null;
            }
        },
        genOptions: function genOptions() {
            var _this2 = this;

            var h = this.$createElement;

            var optionStyle = {
                height: this.itemHeight + 'px'
            };

            return this.options.map(function (option, index) {
                var text = _this2.getOptionText(option);
                var disabled = isOptionDisabled(option);

                var data = {
                    style: optionStyle,
                    attrs: {
                        role: 'button',
                        tabindex: disabled ? -1 : 0
                    },
                    'class': ['sn-ellipsis'].concat(['sn-picker-view-column-item', disabled ? 'sn-picker-view-column-item-disabled' : '', index === _this2.currentIndex ? 'sn-picker-view-column-item-selected' : '']),
                    on: {
                        click: function click() {
                            _this2.onClickItem(index);
                        }
                    }
                };

                if (_this2.allowHtml) {
                    data.domProps = {
                        innerHTML: text
                    };
                }

                return h(
                    'li',
                    data,
                    [_this2.allowHtml ? '' : text]
                );
            });
        }
    },

    render: function render() {
        var h = arguments[0];

        var wrapperStyle = {
            transform: 'translate3d(0, ' + (this.offset + this.baseOffset) + 'px, 0)',
            transitionDuration: this.duration + 'ms',
            transitionProperty: this.duration ? 'all' : 'none',
            lineHeight: this.itemHeight + 'px'
        };

        return h(
            'div',
            {
                'class': this.className,
                on: {
                    'touchstart': this.onTouchStart,
                    'mousedown': this.onMouseStart,
                    'touchmove': this.onTouchMove,
                    'mousemove': this.onMouseMove,
                    'touchend': this.onTouchEnd,
                    'mouseup': this.onMouseEnd,
                    'touchcancel': this.onTouchEnd,
                    'mouseout': this.onMouseEnd,
                    'mousewheel': this.onMouseWheel
                }
            },
            [h(
                'ul',
                {
                    ref: 'wrapper',
                    style: wrapperStyle,
                    'class': 'sn-picker-view-column-wrapper',
                    on: {
                        'transitionend': this.onTransitionEnd
                    }
                },
                [this.genOptions()]
            )]
        );
    }
};

exports['default'] = pickerViewColumn;
module.exports = exports.default;