"use strict";

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

var _lodash = _interopRequireDefault(require("lodash"));

var _postcss = _interopRequireDefault(require("postcss"));

var _postcssSelectorParser = _interopRequireDefault(require("postcss-selector-parser"));

var _generateVariantFunction = _interopRequireDefault(require("../util/generateVariantFunction"));

var _prefixSelector = _interopRequireDefault(require("../util/prefixSelector"));

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function generatePseudoClassVariant(pseudoClass, selectorPrefix = pseudoClass) {
  return (0, _generateVariantFunction.default)(({
    modifySelectors,
    separator
  }) => {
    return modifySelectors(({
      selector
    }) => {
      return (0, _postcssSelectorParser.default)(selectors => {
        selectors.walkClasses(sel => {
          sel.value = `${selectorPrefix}${separator}${sel.value}`;
          sel.parent.insertAfter(sel, _postcssSelectorParser.default.pseudo({
            value: `:${pseudoClass}`
          }));
        });
      }).processSync(selector);
    });
  });
}

function ensureIncludesDefault(variants) {
  return variants.includes('default') ? variants : ['default', ...variants];
}

const defaultVariantGenerators = config => ({
  default: (0, _generateVariantFunction.default)(() => {}),
  'group-hover': (0, _generateVariantFunction.default)(({
    modifySelectors,
    separator
  }) => {
    return modifySelectors(({
      selector
    }) => {
      return (0, _postcssSelectorParser.default)(selectors => {
        selectors.walkClasses(sel => {
          sel.value = `group-hover${separator}${sel.value}`;
          sel.parent.insertBefore(sel, (0, _postcssSelectorParser.default)().astSync((0, _prefixSelector.default)(config.prefix, '.group:hover ')));
        });
      }).processSync(selector);
    });
  }),
  'group-focus': (0, _generateVariantFunction.default)(({
    modifySelectors,
    separator
  }) => {
    return modifySelectors(({
      selector
    }) => {
      return (0, _postcssSelectorParser.default)(selectors => {
        selectors.walkClasses(sel => {
          sel.value = `group-focus${separator}${sel.value}`;
          sel.parent.insertBefore(sel, (0, _postcssSelectorParser.default)().astSync((0, _prefixSelector.default)(config.prefix, '.group:focus ')));
        });
      }).processSync(selector);
    });
  }),
  hover: generatePseudoClassVariant('hover'),
  'focus-within': generatePseudoClassVariant('focus-within'),
  'focus-visible': generatePseudoClassVariant('focus-visible'),
  focus: generatePseudoClassVariant('focus'),
  active: generatePseudoClassVariant('active'),
  visited: generatePseudoClassVariant('visited'),
  disabled: generatePseudoClassVariant('disabled'),
  checked: generatePseudoClassVariant('checked'),
  first: generatePseudoClassVariant('first-child', 'first'),
  last: generatePseudoClassVariant('last-child', 'last'),
  odd: generatePseudoClassVariant('nth-child(odd)', 'odd'),
  even: generatePseudoClassVariant('nth-child(even)', 'even')
});

function _default(config, {
  variantGenerators: pluginVariantGenerators
}) {
  return function (css) {
    const variantGenerators = { ...defaultVariantGenerators(config),
      ...pluginVariantGenerators
    };
    css.walkAtRules('variants', atRule => {
      const variants = _postcss.default.list.comma(atRule.params).filter(variant => variant !== '');

      if (variants.includes('responsive')) {
        const responsiveParent = _postcss.default.atRule({
          name: 'responsive'
        });

        atRule.before(responsiveParent);
        responsiveParent.append(atRule);
      }

      _lodash.default.forEach(_lodash.default.without(ensureIncludesDefault(variants), 'responsive'), variant => {
        if (!variantGenerators[variant]) {
          throw new Error(`Your config mentions the "${variant}" variant, but "${variant}" doesn't appear to be a variant. Did you forget or misconfigure a plugin that supplies that variant?`);
        }

        variantGenerators[variant](atRule, config);
      });

      atRule.remove();
    });
  };
}