"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.separateRtlAndLtr = separateRtlAndLtr;
exports.separateSingleDir = separateSingleDir;

var postcss = _interopRequireWildcard(require("postcss"));

function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }

function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }

const oppositeDir = {
  ltr: 'rtl',
  rtl: 'ltr'
};

function compareSelector(selector1, selector2) {
  return selector1 === selector2;
}

const directionRegexs = {
  ltr: /\[dir=ltr\]/,
  rtl: /\[dir=rtl\]/
};

const getRegex = dir => directionRegexs[dir];

const getOppositeRegex = dir => getRegex(oppositeDir[dir]);

function selectorMinifySameDir(selector, direction) {
  // NOTE: if this rule is same dir as current need
  //  then we can just remove that [dir=ltr] or [dir=rtl]
  //  it just for minimaze selector
  const regex = getRegex(direction);
  return selector.replace(regex, '').trim();
}
/**
 * this funtion will remove given rule,
 *  if given selector and it's previous sibiling rule selector  are same
 * current rule properties will move to previous sibiling rule.
 * @param {Rule} rule current rule
 */


function mergeIfSameSelector(rule) {
  // NOTE: to merge dublicate selector rules
  const prev = rule.prev();

  if (prev && compareSelector(prev.selector, rule.selector)) {
    rule.each(decl => {
      prev.append(decl);
    });
    rule.remove();
  }
}
/**
 * this funtion will remove given rule,
 *  if given selector and it's previous sibiling rule selector  are same
 * current rule properties will move to previous sibiling rule.
 * @param {Rule} rule current rule
 */


function removeIfOppsiteDirRule(rule, direction, rootOptions) {
  const selectors = rule.selector.split(/\s*,\s*/); // NOTE: if we use opposite dir selector as custom override reason,
  //  and compain normal selector with it, In this  case
  //  we just a have to remove that selector only not full rule

  const oppositeDirRegex = getOppositeRegex(direction);
  let remainingSelectors = selectors.filter(selector => !oppositeDirRegex.test(selector));

  if (!rootOptions.disableMiniFiySelector) {
    remainingSelectors = remainingSelectors.map(selector => selectorMinifySameDir(selector, direction));
  }

  if (remainingSelectors.length) {
    rule.selector = remainingSelectors.join(', ');
  } else {
    // NOTE: every selector is opposite dir then we have to remove  the rule
    rule.remove();
  }
}

function removeIfOppsiteDirKeyframe(rule, direction) {
  const name = rule.params;
  const keyFrameDirName = name.slice(name.lastIndexOf('-') + 1);

  if (keyFrameDirName === oppositeDir[direction]) {
    rule.remove();
  }
}

function separateSingleDir(root, direction, rootOptions) {
  root.walkRules(rule => {
    removeIfOppsiteDirRule(rule, direction, rootOptions);
    mergeIfSameSelector(rule);
  });
  root.walkAtRules(rule => {
    removeIfOppsiteDirKeyframe(rule, direction);
  });
  return root;
}

function separateRtlAndLtr(css, rootOptions) {
  // let processor = postcss([]).process(css);
  const root = postcss.parse(css); // let { root } = processor;
  // NOTE: I did first rtl then ltr , Because  for ltr I use original root ref

  const rtlRoot = separateSingleDir(root.clone(), 'rtl', rootOptions);
  const ltrRoot = separateSingleDir(root, 'ltr', rootOptions);
  return {
    ltrRoot,
    rtlRoot,
    ltr: ltrRoot.toString(),
    rtl: rtlRoot.toString()
  };
} // NOTE: to test in https://astexplorer.net/
// you can test with sample input https://astexplorer.net/#/gist/a892a509eb585099355ef53ef094f836/1ca70d5f7af3b88ca4910296e12f118e9712c874
// export default postcss.plugin('postcss-rtl-remove', (options = {}) =>
//   // Work with options here
//   root => {
//     const rtlRoot = separateSingleDir(root.clone(), 'rtl');
//     const ltrRoot = separateSingleDir(root, 'ltr');
//     // root.append(postcss.comment({ text: 'comment' }));
//     root.append(postcss.comment({ text: 'this  is  spliting part ' }));
//     root.append(rtlRoot);
//     // Transform CSS AST here
//   }
// );