import { Layer } from './precedence'

const collator = new Intl.Collator('en', { numeric: true })

export interface SortableRule {
  /** The calculated precedence taking all variants into account. */
  p: number

  /* The precedence of the properties within {@link d}. */
  o: number

  /** The name to use for `&` expansion in selectors. Maybe empty for at-rules like `@import`, `@font-face`, `@media`, ... */
  n?: string | null
}

/**
 * Find the array index of where to add an element to keep it sorted.
 *
 * @returns The insertion index
 */
export function sortedInsertionIndex(
  array: readonly SortableRule[],
  element: SortableRule,
): number {
  // Find position using binary search
  // eslint-disable-next-line no-var
  for (var low = 0, high = array.length; low < high; ) {
    const pivot = (high + low) >> 1

    // Less-Then-Equal to add new equal element after all existing equal elements (stable sort)
    if (compareTwindRules(array[pivot], element) <= 0) {
      low = pivot + 1
    } else {
      high = pivot
    }
  }

  return high
}

export function compareTwindRules(a: SortableRule, b: SortableRule): number {
  // base and overrides (css) layers are kept in order they are declared
  const layer = a.p & Layer.o

  if (layer == (b.p & Layer.o) && (layer == Layer.b || layer == Layer.o)) {
    return 0
  }

  return a.p - b.p || a.o - b.o || collator.compare(a.n as string, b.n as string)
}
