// TODO: it'd be great to merge it with the other canReorder functionality

var rulesOverlap = require('./rules-overlap');
var specificitiesOverlap = require('./specificities-overlap');

var FLEX_PROPERTIES = /align\-items|box\-align|box\-pack|flex|justify/;
var BORDER_PROPERTIES =
  /^border\-(top|right|bottom|left|color|style|width|radius)/;

function canReorder(left, right, cache) {
  for (var i = right.length - 1; i >= 0; i--) {
    for (var j = left.length - 1; j >= 0; j--) {
      if (!canReorderSingle(left[j], right[i], cache)) return false;
    }
  }

  return true;
}

function canReorderSingle(left, right, cache) {
  var leftName = left[0];
  var leftValue = left[1];
  var leftNameRoot = left[2];
  var leftSelector = left[5];
  var leftInSpecificSelector = left[6];
  var rightName = right[0];
  var rightValue = right[1];
  var rightNameRoot = right[2];
  var rightSelector = right[5];
  var rightInSpecificSelector = right[6];

  if (
    (leftName == 'font' && rightName == 'line-height') ||
    (rightName == 'font' && leftName == 'line-height')
  )
    return false;
  if (FLEX_PROPERTIES.test(leftName) && FLEX_PROPERTIES.test(rightName))
    return false;
  if (
    leftNameRoot == rightNameRoot &&
    unprefixed(leftName) == unprefixed(rightName) &&
    vendorPrefixed(leftName) ^ vendorPrefixed(rightName)
  )
    return false;
  if (
    leftNameRoot == 'border' &&
    BORDER_PROPERTIES.test(rightNameRoot) &&
    (leftName == 'border' ||
      leftName == rightNameRoot ||
      (leftValue != rightValue && sameBorderComponent(leftName, rightName)))
  )
    return false;
  if (
    rightNameRoot == 'border' &&
    BORDER_PROPERTIES.test(leftNameRoot) &&
    (rightName == 'border' ||
      rightName == leftNameRoot ||
      (leftValue != rightValue && sameBorderComponent(leftName, rightName)))
  )
    return false;
  if (
    leftNameRoot == 'border' &&
    rightNameRoot == 'border' &&
    leftName != rightName &&
    ((isSideBorder(leftName) && isStyleBorder(rightName)) ||
      (isStyleBorder(leftName) && isSideBorder(rightName)))
  )
    return false;
  if (leftNameRoot != rightNameRoot) return true;
  if (
    leftName == rightName &&
    leftNameRoot == rightNameRoot &&
    (leftValue == rightValue ||
      withDifferentVendorPrefix(leftValue, rightValue))
  )
    return true;
  if (
    leftName != rightName &&
    leftNameRoot == rightNameRoot &&
    leftName != leftNameRoot &&
    rightName != rightNameRoot
  )
    return true;
  if (
    leftName != rightName &&
    leftNameRoot == rightNameRoot &&
    leftValue == rightValue
  )
    return true;
  if (
    rightInSpecificSelector &&
    leftInSpecificSelector &&
    !inheritable(leftNameRoot) &&
    !inheritable(rightNameRoot) &&
    !rulesOverlap(rightSelector, leftSelector, false)
  )
    return true;
  if (!specificitiesOverlap(leftSelector, rightSelector, cache)) return true;

  return false;
}

function vendorPrefixed(name) {
  return /^\-(?:moz|webkit|ms|o)\-/.test(name);
}

function unprefixed(name) {
  return name.replace(/^\-(?:moz|webkit|ms|o)\-/, '');
}

function sameBorderComponent(name1, name2) {
  return name1.split('-').pop() == name2.split('-').pop();
}

function isSideBorder(name) {
  return (
    name == 'border-top' ||
    name == 'border-right' ||
    name == 'border-bottom' ||
    name == 'border-left'
  );
}

function isStyleBorder(name) {
  return (
    name == 'border-color' || name == 'border-style' || name == 'border-width'
  );
}

function withDifferentVendorPrefix(value1, value2) {
  return (
    vendorPrefixed(value1) &&
    vendorPrefixed(value2) &&
    value1.split('-')[1] != value2.split('-')[2]
  );
}

function inheritable(name) {
  // According to http://www.w3.org/TR/CSS21/propidx.html
  // Others will be catched by other, preceeding rules
  return name == 'font' || name == 'line-height' || name == 'list-style';
}

module.exports = {
  canReorder: canReorder,
  canReorderSingle: canReorderSingle,
};