const isPlainObject = require('lodash.isplainobject')

const parser = require('postcss-selector-parser')
const parseSelector = parser()

module.exports = {
  isUsableColor(color, values) {
    return isPlainObject(values) && color !== 'gray' && values[600]
  },

  /**
   * @param {string} selector
   */
  commonTrailingPseudos(selector) {
    let ast = parseSelector.astSync(selector)

    /** @type {import('postcss-selector-parser').Pseudo[][]} */
    let matrix = []

    // Put the pseudo elements in reverse order in a sparse, column-major 2D array
    for (let [i, sel] of ast.nodes.entries()) {
      for (const [j, child] of [...sel.nodes].reverse().entries()) {
        // We only care about pseudo elements
        if (child.type !== 'pseudo' || !child.value.startsWith('::')) {
          break
        }

        matrix[j] = matrix[j] || []
        matrix[j][i] = child
      }
    }

    let trailingPseudos = parser.selector()

    // At this point the pseudo elements are in a column-major 2D array
    // This means each row contains one "column" of pseudo elements from each selector
    // We can compare all the pseudo elements in a row to see if they are the same
    for (const pseudos of matrix) {
      // It's a sparse 2D array so there are going to be holes in the rows
      // We skip those
      if (!pseudos) {
        continue
      }

      let values = new Set([...pseudos.map((p) => p.value)])

      // The pseudo elements are not the same
      if (values.size > 1) {
        break
      }

      pseudos.forEach((pseudo) => pseudo.remove())
      trailingPseudos.prepend(pseudos[0])
    }

    if (trailingPseudos.nodes.length) {
      return [trailingPseudos.toString(), ast.toString()]
    }

    return [null, selector]
  },
}
