import { LokiExpression } from './types';

const selectorRegexp = /(?:^|\s){[^{]*}/g;
export function parseQuery(input: string): LokiExpression {
  input = input || '';
  const match = input.match(selectorRegexp);
  let query = input;
  let regexp = '';

  if (match) {
    // Regexp result is ignored on the server side
    regexp = input.replace(selectorRegexp, '').trim();
    // Keep old-style regexp, otherwise take whole query
    if (regexp && regexp.search(/\|=|\|~|!=|!~/) === -1) {
      query = match[0].trim();
    } else {
      regexp = '';
    }
  }

  return { regexp, query };
}

export function formatQuery(selector: string, search: string): string {
  return `${selector || ''} ${search || ''}`.trim();
}

/**
 * Returns search terms from a LogQL query.
 * E.g., `{} |= foo |=bar != baz` returns `['foo', 'bar']`.
 */
export function getHighlighterExpressionsFromQuery(input: string): string[] {
  const parsed = parseQuery(input);
  // Legacy syntax
  if (parsed.regexp) {
    return [parsed.regexp];
  }
  let expression = input;
  const results = [];
  // Consume filter expression from left to right
  while (expression) {
    const filterStart = expression.search(/\|=|\|~|!=|!~/);
    // Nothing more to search
    if (filterStart === -1) {
      break;
    }
    // Drop terms for negative filters
    const skip = expression.substr(filterStart).search(/!=|!~/) === 0;
    expression = expression.substr(filterStart + 2);
    if (skip) {
      continue;
    }
    // Check if there is more chained
    const filterEnd = expression.search(/\|=|\|~|!=|!~/);
    let filterTerm;
    if (filterEnd === -1) {
      filterTerm = expression.trim();
    } else {
      filterTerm = expression.substr(0, filterEnd).trim();
      expression = expression.substr(filterEnd);
    }

    // Unwrap the filter term by removing quotes
    const quotedTerm = filterTerm.match(/^"((?:[^\\"]|\\")*)"$/);

    if (quotedTerm) {
      const unwrappedFilterTerm = quotedTerm[1];
      results.push(unwrappedFilterTerm);
    } else {
      return null;
    }
  }
  return results;
}
