import equal from 'fast-deep-equal';
import { sliderDefaultProps } from './props';
import fmtEvent from '../_util/fmtEvent';
import createValue from '../mixins/value';
import '../_util/assert-component2';
Component({
    props: sliderDefaultProps,
    mixins: [
        createValue({
            transformValue: function (val, extra, needUpdate, emit) {
                if (needUpdate === void 0) { needUpdate = true; }
                var value = this.formatValue(val);
                if (needUpdate) {
                    this.setSliderStyleByValue(value);
                    this.setTickList();
                }
                this.onChangeValue =
                    typeof this.onChangeValue === 'undefined'
                        ? this.getValue()
                        : this.onChangeValue;
                if (emit &&
                    this.props.onChange &&
                    !this.isSliderValueEqual(this.onChangeValue, value)) {
                    this.onChangeValue = value;
                    this.props.onChange(value, fmtEvent(this.props));
                }
                return {
                    value: value,
                    needUpdate: needUpdate,
                };
            },
        }),
    ],
    data: {
        sliderLeft: 0,
        sliderWidth: 0,
        tickList: [],
        changingStart: false,
        changingEnd: false,
    },
    didUpdate: function (prevProps) {
        if (!equal(this.props.min, prevProps.min) ||
            !equal(this.props.max, prevProps.max) ||
            !equal(this.props.step, prevProps.step) ||
            !equal(this.props.range, prevProps.range) ||
            !equal(this.props.showTicks, prevProps.showTicks)) {
            this.update(this.props.value);
        }
    },
    methods: {
        onChangeValue: undefined,
        formatValue: function (val) {
            var value = this.fitSliderValue(val, this.props.min, this.props.max, this.props.step, this.props.range);
            value = this.getRoundedValue(value, this.props.step);
            return value;
        },
        getRoundedValue: function (value, step) {
            if (step === void 0) { step = 1; }
            if (value === undefined) {
                return 0;
            }
            if (typeof value === 'number') {
                return Math.round(value / step) * step;
            }
            return [
                Math.round(value[0] / step) * step,
                Math.round(value[1] / step) * step,
            ];
        },
        setSliderStyleByValue: function (roundedValue) {
            var _a, _b;
            var leftValue = 0;
            var rightValue = 0;
            var max = (_a = this.props.max) !== null && _a !== void 0 ? _a : sliderDefaultProps.max;
            var min = (_b = this.props.min) !== null && _b !== void 0 ? _b : sliderDefaultProps.min;
            if (roundedValue !== undefined) {
                if (typeof roundedValue === 'number') {
                    leftValue = min;
                    rightValue = roundedValue;
                }
                else {
                    leftValue = roundedValue[0];
                    rightValue = roundedValue[1];
                }
            }
            // FIX_ME when min and max is equal
            var width = ((rightValue - leftValue) / (max - min)) * 100;
            var left = ((leftValue - min) / (max - min)) * 100;
            this.setData({
                sliderLeft: left,
                sliderWidth: width,
            });
        },
        setTickList: function () {
            var _a = this.props, step = _a.step, min = _a.min, max = _a.max, showTicks = _a.showTicks;
            if (!showTicks) {
                return;
            }
            var tickList = [];
            var stepCount = (max - min) / step;
            for (var i = 0; i <= stepCount; i += 1) {
                tickList.push({
                    left: i * (100 / stepCount),
                    value: i * step + min,
                });
            }
            this.setData({
                tickList: tickList,
            });
        },
        onTouchChanged: function (e, type) {
            var _this = this;
            if (this.props.disabled) {
                return;
            }
            var changeMoving = function (params) {
                var newParams = {};
                for (var key in params) {
                    if (params[key] !== _this.data[key]) {
                        newParams[key] = params[key];
                    }
                }
                if (Object.keys(newParams).length > 0) {
                    _this.setData(newParams);
                }
            };
            if (e.currentTarget && e.changedTouches[0]) {
                // eslint-disable-next-line @typescript-eslint/ban-ts-comment
                // @ts-ignore
                my.createSelectorQuery()
                    .select("#".concat(e.currentTarget.id))
                    .boundingClientRect()
                    .exec(function (list) {
                    var element = list[0];
                    if (element) {
                        var touch = e.changedTouches[0];
                        var touchPosition = (touch.pageX - element.left) / element.width;
                        var value = _this.props.min +
                            touchPosition * (_this.props.max - _this.props.min);
                        if (!_this.props.range) {
                            _this.update(value, {}, !_this.isControlled(), true);
                            changeMoving({ changingEnd: true });
                        }
                        else {
                            var currentValue = _this.getValue();
                            var leftValue = currentValue[0];
                            var rightValue = currentValue[1];
                            var leftDistance = Math.abs(leftValue - value);
                            var rightDistance = Math.abs(rightValue - value);
                            var isFarFromLeft = leftDistance > rightDistance;
                            var farValue = isFarFromLeft ? leftValue : rightValue;
                            _this.update([value, farValue], {}, !_this.isControlled(), 'onChange');
                            if (isFarFromLeft) {
                                changeMoving({ changingEnd: true });
                            }
                            else {
                                changeMoving({ changingStart: true });
                            }
                        }
                    }
                    if (type === 'end') {
                        changeMoving({ changingEnd: false, changingStart: false });
                        if (_this.props.onAfterChange) {
                            _this.props.onAfterChange(_this.getValue(), fmtEvent(_this.props, e));
                        }
                    }
                });
            }
        },
        cloneSliderValue: function (value) {
            if (typeof value === 'object') {
                return [value[0], value[1]];
            }
            return value;
        },
        isSliderValueEqual: function (value1, value2) {
            if (value1 === value2) {
                return true;
            }
            if (value1 === undefined || value2 === undefined) {
                return false;
            }
            if (typeof value1 === 'number' || typeof value2 == 'number') {
                return value1 === value2;
            }
            if (value1[0] === value2[0] && value1[1] === value2[1]) {
                return true;
            }
            return false;
        },
        fitSliderValue: function (value, min, max, step, isRange) {
            if (value === undefined) {
                if (isRange) {
                    return [min, min];
                }
                else {
                    return min !== null && min !== void 0 ? min : 0;
                }
            }
            if (typeof value === 'number') {
                if (value > max) {
                    return max;
                }
                if (value < min) {
                    return min;
                }
                return value;
            }
            var leftValue = Math.min(value[0], value[1]);
            var rightValue = Math.max(value[0], value[1]);
            return [
                Math.max(min, leftValue),
                Math.min(max, rightValue),
            ];
        },
        handleTrackTouchStart: function (e) {
            this.onTouchChanged(e, 'start');
        },
        handleTrackTouchMove: function (e) {
            this.onTouchChanged(e, 'move');
        },
        handleTrackTouchEnd: function (e) {
            this.onTouchChanged(e, 'end');
        },
    },
});
