import valueParser from 'postcss-value-parser';

/*
 * Constants (parser usage)
 */

const SINGLE_QUOTE = "'".charCodeAt(0);
const DOUBLE_QUOTE = '"'.charCodeAt(0);
const BACKSLASH = '\\'.charCodeAt(0);
const NEWLINE = '\n'.charCodeAt(0);
const SPACE = ' '.charCodeAt(0);
const FEED = '\f'.charCodeAt(0);
const TAB = '\t'.charCodeAt(0);
const CR = '\r'.charCodeAt(0);

const WORD_END = /[ \n\t\r\f'"\\]/g;

/*
 * Constants (node type strings)
 */

const C_STRING = 'string';
const C_ESCAPED_SINGLE_QUOTE = 'escapedSingleQuote';
const C_ESCAPED_DOUBLE_QUOTE = 'escapedDoubleQuote';
const C_SINGLE_QUOTE = 'singleQuote';
const C_DOUBLE_QUOTE = 'doubleQuote';
const C_NEWLINE = 'newline';
const C_SINGLE = 'single';

/*
 * Literals
 */

const L_SINGLE_QUOTE = `'`;
const L_DOUBLE_QUOTE = `"`;
const L_NEWLINE = `\\\n`;

/*
 * Parser nodes
 */

const T_ESCAPED_SINGLE_QUOTE = { type: C_ESCAPED_SINGLE_QUOTE, value: `\\'` };
const T_ESCAPED_DOUBLE_QUOTE = { type: C_ESCAPED_DOUBLE_QUOTE, value: `\\"` };
const T_SINGLE_QUOTE = { type: C_SINGLE_QUOTE, value: L_SINGLE_QUOTE };
const T_DOUBLE_QUOTE = { type: C_DOUBLE_QUOTE, value: L_DOUBLE_QUOTE };
const T_NEWLINE = { type: C_NEWLINE, value: L_NEWLINE };

/** @typedef {typeof T_ESCAPED_SINGLE_QUOTE | typeof T_ESCAPED_DOUBLE_QUOTE | typeof T_SINGLE_QUOTE | typeof T_NEWLINE} StringAstNode */
/**
 * @typedef {{nodes: StringAstNode[],
 *            types: {escapedSingleQuote: number, escapedDoubleQuote: number, singleQuote: number, doubleQuote: number},
 *            quotes: boolean}} StringAst
 */

/**
 * @param {StringAst} ast
 * @return {string}
 */
function stringify(ast) {
  let str = '';
  for (const { value } of ast.nodes) {
    // Collapse multiple line strings automatically
    if (value !== L_NEWLINE) {
      str += value;
    }
  }
  return str;
}

/**
 * @param {string} str
 * @return {StringAst}
 */
function parse(str) {
  let code, next, value;
  let pos = 0;
  const len = str.length;

  /** @type StringAst */
  const ast = {
    nodes: [],
    types: {
      escapedSingleQuote: 0,
      escapedDoubleQuote: 0,
      singleQuote: 0,
      doubleQuote: 0,
    },
    quotes: false,
  };

  while (pos < len) {
    code = str.charCodeAt(pos);

    switch (code) {
      case SPACE:
      case TAB:
      case CR:
      case FEED:
        next = pos;

        do {
          next += 1;
          code = str.charCodeAt(next);
        } while (
          code === SPACE ||
          code === NEWLINE ||
          code === TAB ||
          code === CR ||
          code === FEED
        );

        ast.nodes.push({
          type: 'space',
          value: str.slice(pos, next),
        });
        pos = next - 1;
        break;
      case SINGLE_QUOTE:
        ast.nodes.push(T_SINGLE_QUOTE);
        ast.types[C_SINGLE_QUOTE]++;
        ast.quotes = true;
        break;
      case DOUBLE_QUOTE:
        ast.nodes.push(T_DOUBLE_QUOTE);
        ast.types[C_DOUBLE_QUOTE]++;
        ast.quotes = true;
        break;
      case BACKSLASH:
        next = pos + 1;

        if (str.charCodeAt(next) === SINGLE_QUOTE) {
          ast.nodes.push(T_ESCAPED_SINGLE_QUOTE);
          ast.types[C_ESCAPED_SINGLE_QUOTE]++;
          ast.quotes = true;
          pos = next;
          break;
        } else if (str.charCodeAt(next) === DOUBLE_QUOTE) {
          ast.nodes.push(T_ESCAPED_DOUBLE_QUOTE);
          ast.types[C_ESCAPED_DOUBLE_QUOTE]++;
          ast.quotes = true;
          pos = next;
          break;
        } else if (str.charCodeAt(next) === NEWLINE) {
          ast.nodes.push(T_NEWLINE);
          pos = next;
          break;
        }
      /*
       * We need to fall through here to handle the token as
       * a whole word. The missing 'break' is intentional.
       */
      // oxlint-disable-next-line no-fallthrough
      default:
        WORD_END.lastIndex = pos + 1;
        WORD_END.test(str);

        if (WORD_END.lastIndex === 0) {
          next = len - 1;
        } else {
          next = WORD_END.lastIndex - 2;
        }

        value = str.slice(pos, next + 1);

        ast.nodes.push({
          type: C_STRING,
          value,
        });

        pos = next;
    }
    pos++;
  }

  return ast;
}

/**
 * @param {valueParser.StringNode} node
 * @param {StringAst} ast
 * @return {void}
 */
function changeWrappingQuotes(node, ast) {
  const { types } = ast;

  if (types[C_SINGLE_QUOTE] || types[C_DOUBLE_QUOTE]) {
    return;
  }

  if (
    node.quote === L_SINGLE_QUOTE &&
    types[C_ESCAPED_SINGLE_QUOTE] > 0 &&
    !types[C_ESCAPED_DOUBLE_QUOTE]
  ) {
    node.quote = L_DOUBLE_QUOTE;
  }

  if (
    node.quote === L_DOUBLE_QUOTE &&
    types[C_ESCAPED_DOUBLE_QUOTE] > 0 &&
    !types[C_ESCAPED_SINGLE_QUOTE]
  ) {
    node.quote = L_SINGLE_QUOTE;
  }

  ast.nodes = changeChildQuotes(ast.nodes, node.quote);
}
/**
 * @param {StringAstNode[]} childNodes
 * @param {string} parentQuote
 * @return {StringAstNode[]}
 */
function changeChildQuotes(childNodes, parentQuote) {
  const updatedChildren = [];
  for (const child of childNodes) {
    if (
      child.type === C_ESCAPED_DOUBLE_QUOTE &&
      parentQuote === L_SINGLE_QUOTE
    ) {
      updatedChildren.push(T_DOUBLE_QUOTE);
    } else if (
      child.type === C_ESCAPED_SINGLE_QUOTE &&
      parentQuote === L_DOUBLE_QUOTE
    ) {
      updatedChildren.push(T_SINGLE_QUOTE);
    } else {
      updatedChildren.push(child);
    }
  }
  return updatedChildren;
}

/**
 * @param {string} value
 * @param {'single' | 'double'} preferredQuote
 * @return {string}
 */
function normalize(value, preferredQuote) {
  if (!value || !value.length) {
    return value;
  }

  return valueParser(value)
    .walk((child) => {
      if (child.type !== C_STRING) {
        return;
      }

      const ast = parse(child.value);

      if (ast.quotes) {
        changeWrappingQuotes(child, ast);
      } else if (preferredQuote === C_SINGLE) {
        child.quote = L_SINGLE_QUOTE;
      } else {
        child.quote = L_DOUBLE_QUOTE;
      }

      child.value = stringify(ast);
    })
    .toString();
}

/**
 * @param {string} original
 * @param {Map<string, string>} cache
 * @param {'single' | 'double'} preferredQuote
 * @return {string}
 */
function minify(original, cache, preferredQuote) {
  const key = original + '|' + preferredQuote;
  if (cache.has(key)) {
    return /** @type {string} */ (cache.get(key));
  }
  const newValue = normalize(original, preferredQuote);
  cache.set(key, newValue);
  return newValue;
}

/** @typedef {{preferredQuote?: 'double' | 'single'}} Options */
/**
 * @param {Options} opts
 * @return {import('postcss').Plugin}
 */
function pluginCreator(opts) {
  const { preferredQuote } = Object.assign(
    {},
    {
      preferredQuote: 'double',
    },
    opts
  );

  return {
    postcssPlugin: 'postcss-normalize-string',

    /**
     * @param {import('postcss').Root} css
     */
    OnceExit(css) {
      const cache = new Map();

      css.walk((node) => {
        switch (node.type) {
          case 'rule':
            node.selector = minify(node.selector, cache, preferredQuote);
            break;
          case 'decl':
            node.value = minify(node.value, cache, preferredQuote);
            break;
          case 'atrule':
            node.params = minify(node.params, cache, preferredQuote);
            break;
        }
      });
    },
  };
}
/** @type {true} */
pluginCreator.postcss = true;
const moduleExports = pluginCreator;

export { moduleExports as default, moduleExports as 'module.exports' };
