"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.motion = void 0;

var _attach = require("./attach");

var _util = require("../../../util");

function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }

function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }

function _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }

function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }

var getStylePropertyValue = function getStylePropertyValue(decl, property) {
  return decl.getPropertyValue(property);
};

var configRE = /((?:\d?\.)?\d+(?:ms|s))\s([\s\S]+)/;

var parseConfig = function parseConfig(config) {
  var _config$match = config.match(configRE),
      _config$match2 = _slicedToArray(_config$match, 3),
      duration = _config$match2[1],
      easing = _config$match2[2];

  return {
    duration: duration,
    easing: easing
  };
};

var numberifyDuration = function numberifyDuration(duration) {
  if (/ms$/.test(duration)) {
    return parseFloat(duration.slice(0, -2));
  } else if (/s$/.test(duration)) {
    return parseFloat(duration.slice(0, -1)) * 1000;
  } else {
    throw new Error('Numberify duration failed.');
  }
};

var motion = function motion(config, initial, end, delay) {
  var duration;
  var easing;

  if (typeof config === 'number') {
    duration = config.toString();
  } else {
    var ret = parseConfig(config);
    duration = ret.duration;
    easing = ret.easing || 'ease';
  }

  if (duration == null) {
    throw new Error('transition duration should be specified.');
  }

  return function (el, callback) {
    var orginStyle = el.getAttribute('style');
    var currentStyle = {};
    var computedStyle = window.getComputedStyle(el);
    var transitionRule = [];
    var hiddenRule = '';

    for (var i in initial) {
      if (Object.prototype.hasOwnProperty.call(initial, i) && initial[i] != null) {
        var propertyName = _util.str.hyphenate(i);

        transitionRule.push("".concat(propertyName, " ").concat(duration, " ").concat(easing));
        currentStyle[i] = getStylePropertyValue(computedStyle, propertyName);

        if (i === 'height') {
          hiddenRule = hiddenRule || 'overflow: hidden;';
          el.style['overflow'] = 'hidden';
        }

        if (initial[i] === '*') {
          el.style[i] = currentStyle[i];
        } else {
          el.style[i] = initial[i];
        }
      }
    } // 强制触发重排以保证动画的执行


    _util.dom.forceReflow(el);

    var run = function run(motionToken) {
      el.style.cssText = "\n        ".concat(orginStyle, "; transition: ").concat(transitionRule.join(', '), "; ").concat(hiddenRule, "\n      ");

      for (var _i2 in end) {
        if (end.hasOwnProperty(_i2) && end[_i2] != null) {
          if (end[_i2] === '*') {
            el.style[_i2] = currentStyle[_i2];
          } else {
            el.style[_i2] = end[_i2];
          }
        }
      }

      (0, _attach.attach)(el, orginStyle, numberifyDuration(duration), motionToken).then(function () {
        return callback();
      })["catch"](function (err) {
        if (!err.canceled) {
          callback();
        }
      });
      return function () {
        if (motionToken && _util.func.isFunction(motionToken.cancel)) {
          motionToken.cancel();
        }
      };
    };

    var token = Object.create(null);

    if (typeof delay === 'number') {
      var handler = null;
      var timeoutId = window.setTimeout(function () {
        handler = run(token);
      }, delay);
      return function () {
        if (!_util.func.isFunction(handler) && timeoutId) {
          window.clearTimeout(timeoutId);
        } else if (_util.func.isFunction(handler)) {
          handler();
        }
      };
    } else {
      return run(token);
    }
  };
};

exports.motion = motion;