export type CflintParserCompatMode = 'auto' | 'off';

export interface CflintCompatibilityRewrite {
  content: string;
  replacementCount: number;
}

export function normalizeCflintParserCompatMode(value?: string): CflintParserCompatMode {
  return value?.trim().toLowerCase() === 'off' ? 'off' : 'auto';
}

/**
 * CFLint 1.5.x embeds CFParser 2.11.0, whose grammar does not recognize the
 * Lucee strict equality operators. The replacements are intentionally the
 * same length as the source operators so CFLint line, column and offset
 * diagnostics remain aligned with the original file.
 *
 * This content is only written to an isolated lint input. The source file is
 * never rewritten by this compatibility step.
 */
export function rewriteStrictEqualityForCflint(source: string): CflintCompatibilityRewrite {
  let replacementCount = 0;
  let content = '';
  let index = 0;
  let state: 'code' | 'single-quote' | 'double-quote' | 'line-comment' | 'block-comment' | 'cfml-comment' = 'code';

  while (index < source.length) {
    if (state === 'code') {
      if (source.startsWith('<!---', index)) {
        state = 'cfml-comment';
        content += '<!---';
        index += 5;
        continue;
      }
      if (source.startsWith('//', index)) {
        state = 'line-comment';
        content += '//';
        index += 2;
        continue;
      }
      if (source.startsWith('/*', index)) {
        state = 'block-comment';
        content += '/*';
        index += 2;
        continue;
      }
      if (source[index] === "'") {
        state = 'single-quote';
        content += source[index++];
        continue;
      }
      if (source[index] === '"') {
        state = 'double-quote';
        content += source[index++];
        continue;
      }
      if (source.startsWith('!==', index)) {
        content += '!= ';
        replacementCount += 1;
        index += 3;
        continue;
      }
      if (source.startsWith('===', index)) {
        content += '== ';
        replacementCount += 1;
        index += 3;
        continue;
      }
    } else if (state === 'line-comment' && (source[index] === '\n' || source[index] === '\r')) {
      state = 'code';
    } else if (state === 'block-comment' && source.startsWith('*/', index)) {
      state = 'code';
      content += '*/';
      index += 2;
      continue;
    } else if (state === 'cfml-comment' && source.startsWith('--->', index)) {
      state = 'code';
      content += '--->';
      index += 4;
      continue;
    } else if (state === 'single-quote' && source[index] === "'") {
      if (source[index + 1] === "'") {
        content += "''";
        index += 2;
        continue;
      }
      state = 'code';
    } else if (state === 'double-quote' && source[index] === '"') {
      if (source[index + 1] === '"') {
        content += '""';
        index += 2;
        continue;
      }
      state = 'code';
    }

    content += source[index++];
  }

  return { content, replacementCount };
}
