text: 'use strict';
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  
  var _utils = require('../utils');
  
  var _utils2 = _interopRequireDefault(_utils);
  
  var _getVisibleRectForElement = require('../getVisibleRectForElement');
  
  var _getVisibleRectForElement2 = _interopRequireDefault(_getVisibleRectForElement);
  
  var _adjustForViewport = require('../adjustForViewport');
  
  var _adjustForViewport2 = _interopRequireDefault(_adjustForViewport);
  
  var _getRegion = require('../getRegion');
  
  var _getRegion2 = _interopRequireDefault(_getRegion);
  
  var _getElFuturePos = require('../getElFuturePos');
  
  var _getElFuturePos2 = _interopRequireDefault(_getElFuturePos);
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
  
  // http://yiminghe.iteye.com/blog/1124720
  
  function isFailX(elFuturePos, elRegion, visibleRect) {
    return elFuturePos.left < visibleRect.left || elFuturePos.left + elRegion.width > visibleRect.right;
  } /**
     * align dom node flexibly
     * @author yiminghe@gmail.com
     */
  
  function isFailY(elFuturePos, elRegion, visibleRect) {
    return elFuturePos.top < visibleRect.top || elFuturePos.top + elRegion.height > visibleRect.bottom;
  }
  
  function isCompleteFailX(elFuturePos, elRegion, visibleRect) {
    return elFuturePos.left > visibleRect.right || elFuturePos.left + elRegion.width < visibleRect.left;
  }
  
  function isCompleteFailY(elFuturePos, elRegion, visibleRect) {
    return elFuturePos.top > visibleRect.bottom || elFuturePos.top + elRegion.height < visibleRect.top;
  }
  
  function flip(points, reg, map) {
    var ret = [];
    _utils2['default'].each(points, function (p) {
      ret.push(p.replace(reg, function (m) {
        return map[m];
      }));
    });
    return ret;
  }
  
  function flipOffset(offset, index) {
    offset[index] = -offset[index];
    return offset;
  }
  
  function convertOffset(str, offsetLen) {
    var n = void 0;
    if (/%$/.test(str)) {
      n = parseInt(str.substring(0, str.length - 1), 10) / 100 * offsetLen;
    } else {
      n = parseInt(str, 10);
    }
    return n || 0;
  }
  
  function normalizeOffset(offset, el) {
    offset[0] = convertOffset(offset[0], el.width);
    offset[1] = convertOffset(offset[1], el.height);
  }
  
  /**
   * @param el
   * @param tgtRegion 参照节点所占的区域: { left, top, width, height }
   * @param align
   */
  function doAlign(el, tgtRegion, align, isTgtRegionVisible) {
    var points = align.points;
    var offset = align.offset || [0, 0];
    var targetOffset = align.targetOffset || [0, 0];
    var overflow = align.overflow;
    var source = align.source || el;
    offset = [].concat(offset);
    targetOffset = [].concat(targetOffset);
    overflow = overflow || {};
    var newOverflowCfg = {};
    var fail = 0;
    // 当前节点可以被放置的显示区域
    var visibleRect = (0, _getVisibleRectForElement2['default'])(source);
    // 当前节点所占的区域, left/top/width/height
    var elRegion = (0, _getRegion2['default'])(source);
    // 将 offset 转换成数值，支持百分比
    normalizeOffset(offset, elRegion);
    normalizeOffset(targetOffset, tgtRegion);
    // 当前节点将要被放置的位置
    var elFuturePos = (0, _getElFuturePos2['default'])(elRegion, tgtRegion, points, offset, targetOffset);
    // 当前节点将要所处的区域
    var newElRegion = _utils2['default'].merge(elRegion, elFuturePos);
  
    // 如果可视区域不能完全放置当前节点时允许调整
    if (visibleRect && (overflow.adjustX || overflow.adjustY) && isTgtRegionVisible) {
      if (overflow.adjustX) {
        // 如果横向不能放下
        if (isFailX(elFuturePos, elRegion, visibleRect)) {
          // 对齐位置反下
          var newPoints = flip(points, /[lr]/ig, {
            l: 'r',
            r: 'l'
          });
          // 偏移量也反下
          var newOffset = flipOffset(offset, 0);
          var newTargetOffset = flipOffset(targetOffset, 0);
          var newElFuturePos = (0, _getElFuturePos2['default'])(elRegion, tgtRegion, newPoints, newOffset, newTargetOffset);
  
          if (!isCompleteFailX(newElFuturePos, elRegion, visibleRect)) {
            fail = 1;
            points = newPoints;
            offset = newOffset;
            targetOffset = newTargetOffset;
          }
        }
      }
  
      if (overflow.adjustY) {
        // 如果纵向不能放下
        if (isFailY(elFuturePos, elRegion, visibleRect)) {
          // 对齐位置反下
          var _newPoints = flip(points, /[tb]/ig, {
            t: 'b',
            b: 't'
          });
          // 偏移量也反下
          var _newOffset = flipOffset(offset, 1);
          var _newTargetOffset = flipOffset(targetOffset, 1);
          var _newElFuturePos = (0, _getElFuturePos2['default'])(elRegion, tgtRegion, _newPoints, _newOffset, _newTargetOffset);
  
          if (!isCompleteFailY(_newElFuturePos, elRegion, visibleRect)) {
            fail = 1;
            points = _newPoints;
            offset = _newOffset;
            targetOffset = _newTargetOffset;
          }
        }
      }
  
      // 如果失败，重新计算当前节点将要被放置的位置
      if (fail) {
        elFuturePos = (0, _getElFuturePos2['default'])(elRegion, tgtRegion, points, offset, targetOffset);
        _utils2['default'].mix(newElRegion, elFuturePos);
      }
      var isStillFailX = isFailX(elFuturePos, elRegion, visibleRect);
      var isStillFailY = isFailY(elFuturePos, elRegion, visibleRect);
      // 检查反下后的位置是否可以放下了，如果仍然放不下：
      // 1. 复原修改过的定位参数
      if (isStillFailX || isStillFailY) {
        points = align.points;
        offset = align.offset || [0, 0];
        targetOffset = align.targetOffset || [0, 0];
      }
      // 2. 只有指定了可以调整当前方向才调整
      newOverflowCfg.adjustX = overflow.adjustX && isStillFailX;
      newOverflowCfg.adjustY = overflow.adjustY && isStillFailY;
  
      // 确实要调整，甚至可能会调整高度宽度
      if (newOverflowCfg.adjustX || newOverflowCfg.adjustY) {
        newElRegion = (0, _adjustForViewport2['default'])(elFuturePos, elRegion, visibleRect, newOverflowCfg);
      }
    }
  
    // need judge to in case set fixed with in css on height auto element
    if (newElRegion.width !== elRegion.width) {
      _utils2['default'].css(source, 'width', _utils2['default'].width(source) + newElRegion.width - elRegion.width);
    }
  
    if (newElRegion.height !== elRegion.height) {
      _utils2['default'].css(source, 'height', _utils2['default'].height(source) + newElRegion.height - elRegion.height);
    }
  
    // https://github.com/kissyteam/kissy/issues/190
    // 相对于屏幕位置没变，而 left/top 变了
    // 例如 <div 'relative'><el absolute></div>
    _utils2['default'].offset(source, {
      left: newElRegion.left,
      top: newElRegion.top
    }, {
      useCssRight: align.useCssRight,
      useCssBottom: align.useCssBottom,
      useCssTransform: align.useCssTransform
    });
  
    return {
      points: points,
      offset: offset,
      targetOffset: targetOffset,
      overflow: newOverflowCfg
    };
  }
  
  exports['default'] = doAlign;
  /**
   *  2012-04-26 yiminghe@gmail.com
   *   - 优化智能对齐算法
   *   - 慎用 resizeXX
   *
   *  2011-07-13 yiminghe@gmail.com note:
   *   - 增加智能对齐，以及大小调整选项
   **/
  
  module.exports = exports['default'];