import { createNamespace, addUnit } from '../utils';
import { deepClone } from '../utils/deep-clone';
import { preventDefault } from '../utils/dom/event';
import { range, addNumber } from '../utils/format/number';
import { TouchMixin } from '../mixins/touch';
import { FieldMixin } from '../mixins/field';

var _createNamespace = createNamespace('slider'),
    createComponent = _createNamespace[0],
    bem = _createNamespace[1];

var isSameValue = function isSameValue(newValue, oldValue) {
  return JSON.stringify(newValue) === JSON.stringify(oldValue);
};

export default createComponent({
  mixins: [TouchMixin, FieldMixin],
  props: {
    disabled: Boolean,
    vertical: Boolean,
    range: Boolean,
    barHeight: [Number, String],
    buttonSize: [Number, String],
    activeColor: String,
    inactiveColor: String,
    min: {
      type: [Number, String],
      default: 0
    },
    max: {
      type: [Number, String],
      default: 100
    },
    step: {
      type: [Number, String],
      default: 1
    },
    value: {
      type: [Number, Array],
      default: 0
    }
  },
  data: function data() {
    return {
      dragStatus: ''
    };
  },
  computed: {
    scope: function scope() {
      return this.max - this.min;
    },
    buttonStyle: function buttonStyle() {
      if (this.buttonSize) {
        var size = addUnit(this.buttonSize);
        return {
          width: size,
          height: size
        };
      }
    }
  },
  created: function created() {
    // format initial value
    this.updateValue(this.value);
  },
  mounted: function mounted() {
    if (this.range) {
      this.bindTouchEvent(this.$refs.wrapper0);
      this.bindTouchEvent(this.$refs.wrapper1);
    } else {
      this.bindTouchEvent(this.$refs.wrapper);
    }
  },
  methods: {
    onTouchStart: function onTouchStart(event) {
      if (this.disabled) {
        return;
      }

      this.touchStart(event);
      this.currentValue = this.value;

      if (this.range) {
        this.startValue = this.value.map(this.format);
      } else {
        this.startValue = this.format(this.value);
      }

      this.dragStatus = 'start';
    },
    onTouchMove: function onTouchMove(event) {
      if (this.disabled) {
        return;
      }

      if (this.dragStatus === 'start') {
        this.$emit('drag-start');
      }

      preventDefault(event, true);
      this.touchMove(event);
      this.dragStatus = 'draging';
      var rect = this.$el.getBoundingClientRect();
      var delta = this.vertical ? this.deltaY : this.deltaX;
      var total = this.vertical ? rect.height : rect.width;
      var diff = delta / total * this.scope;

      if (this.range) {
        this.currentValue[this.index] = this.startValue[this.index] + diff;
      } else {
        this.currentValue = this.startValue + diff;
      }

      this.updateValue(this.currentValue);
    },
    onTouchEnd: function onTouchEnd() {
      if (this.disabled) {
        return;
      }

      if (this.dragStatus === 'draging') {
        this.updateValue(this.currentValue, true);
        this.$emit('drag-end');
      }

      this.dragStatus = '';
    },
    onClick: function onClick(event) {
      event.stopPropagation();
      if (this.disabled) return;
      var rect = this.$el.getBoundingClientRect();
      var delta = this.vertical ? event.clientY - rect.top : event.clientX - rect.left;
      var total = this.vertical ? rect.height : rect.width;
      var value = +this.min + delta / total * this.scope;

      if (this.range) {
        var _this$value = this.value,
            left = _this$value[0],
            right = _this$value[1];
        var middle = (left + right) / 2;

        if (value <= middle) {
          left = value;
        } else {
          right = value;
        }

        value = [left, right];
      }

      this.startValue = this.value;
      this.updateValue(value, true);
    },
    // 处理两个滑块重叠之后的情况
    handleOverlap: function handleOverlap(value) {
      if (value[0] > value[1]) {
        value = deepClone(value);
        return value.reverse();
      }

      return value;
    },
    updateValue: function updateValue(value, end) {
      if (this.range) {
        value = this.handleOverlap(value).map(this.format);
      } else {
        value = this.format(value);
      }

      if (!isSameValue(value, this.value)) {
        this.$emit('input', value);
      }

      if (end && !isSameValue(value, this.startValue)) {
        this.$emit('change', value);
      }
    },
    format: function format(value) {
      var min = +this.min;
      var max = +this.max;
      var step = +this.step;
      value = range(value, min, max);
      var diff = Math.round((value - min) / step) * step;
      return addNumber(min, diff);
    }
  },
  render: function render() {
    var _wrapperStyle,
        _this = this,
        _barStyle;

    var h = arguments[0];
    var vertical = this.vertical;
    var mainAxis = vertical ? 'height' : 'width';
    var crossAxis = vertical ? 'width' : 'height';
    var wrapperStyle = (_wrapperStyle = {
      background: this.inactiveColor
    }, _wrapperStyle[crossAxis] = addUnit(this.barHeight), _wrapperStyle); // 计算选中条的长度百分比

    var calcMainAxis = function calcMainAxis() {
      var value = _this.value,
          min = _this.min,
          range = _this.range,
          scope = _this.scope;

      if (range) {
        return (value[1] - value[0]) * 100 / scope + "%";
      }

      return (value - min) * 100 / scope + "%";
    }; // 计算选中条的开始位置的偏移量


    var calcOffset = function calcOffset() {
      var value = _this.value,
          min = _this.min,
          range = _this.range,
          scope = _this.scope;

      if (range) {
        return (value[0] - min) * 100 / scope + "%";
      }

      return null;
    };

    var barStyle = (_barStyle = {}, _barStyle[mainAxis] = calcMainAxis(), _barStyle.left = this.vertical ? null : calcOffset(), _barStyle.top = this.vertical ? calcOffset() : null, _barStyle.background = this.activeColor, _barStyle);

    if (this.dragStatus) {
      barStyle.transition = 'none';
    }

    var renderButton = function renderButton(i) {
      var map = ['left', 'right'];
      var isNumber = typeof i === 'number';
      var current = isNumber ? _this.value[i] : _this.value;

      var getClassName = function getClassName() {
        if (isNumber) {
          return "button-wrapper-" + map[i];
        }

        return "button-wrapper";
      };

      var getRefName = function getRefName() {
        if (isNumber) {
          return "wrapper" + i;
        }

        return "wrapper";
      };

      var renderButtonContent = function renderButtonContent() {
        if (isNumber) {
          var slot = _this.slots(i === 0 ? 'left-button' : 'right-button', {
            value: current
          });

          if (slot) {
            return slot;
          }
        }

        if (_this.slots('button')) {
          return _this.slots('button');
        }

        return h("div", {
          "class": bem('button'),
          "style": _this.buttonStyle
        });
      };

      return h("div", {
        "ref": getRefName(),
        "attrs": {
          "role": "slider",
          "tabindex": _this.disabled ? -1 : 0,
          "aria-valuemin": _this.min,
          "aria-valuenow": _this.value,
          "aria-valuemax": _this.max,
          "aria-orientation": _this.vertical ? 'vertical' : 'horizontal'
        },
        "class": bem(getClassName()),
        "on": {
          "touchstart": function touchstart() {
            if (isNumber) {
              // 保存当前按钮的索引
              _this.index = i;
            }
          },
          "click": function click(e) {
            return e.stopPropagation();
          }
        }
      }, [renderButtonContent()]);
    };

    return h("div", {
      "style": wrapperStyle,
      "class": bem({
        disabled: this.disabled,
        vertical: vertical
      }),
      "on": {
        "click": this.onClick
      }
    }, [h("div", {
      "class": bem('bar'),
      "style": barStyle
    }, [this.range ? [renderButton(0), renderButton(1)] : renderButton()])]);
  }
});