import { Arr, Optional } from '@ephox/katamari';
import { WordScope } from '../data/WordScope';

const quoteList = [ `'`, '\u2018', '\u2019' ];
const whitelist = Arr.bind(quoteList, (q) => {
  return Arr.map([ 'twas' ], (t) => {
    return q + t;
  });
});

const trimStart = (ws: WordScope): WordScope => {
  const word = ws.word;
  return WordScope(word.substring(1), Optional.some(word.charAt(0)), ws.right);
};

const trimEnd = (ws: WordScope): WordScope => {
  const word = ws.word;
  return WordScope(word.substring(0, word.length - 1), ws.left, Optional.some(word.charAt(word.length - 1)));
};

const isQuote = (s: string): boolean => {
  return Arr.contains(quoteList, s);
};

const rhs = (ws: WordScope): WordScope => {
  const word = ws.word;
  const trailing = word.length >= 2 && isQuote(word.charAt(word.length - 1)) && !isQuote(word.charAt(word.length - 2));
  return trailing ? trimEnd(ws) : ws;
};

const lhs = (ws: WordScope): WordScope => {
  const word = ws.word;
  const whitelisted = Arr.exists(whitelist, (x) => {
    return word.indexOf(x) > -1;
  });

  const apostrophes = whitelisted ? 2 : 1;
  const quoted = word.substring(0, apostrophes);

  const leading = Arr.forall(quoted, isQuote) && !isQuote(word.charAt(apostrophes));

  return leading ? trimStart(ws) : ws;
};

/**
 * If there are quotes at the edges of the WordScope, this determines if they are part of the word
 *
 * ws: WordScope
 */
const scope = (ws: WordScope): WordScope => {
  const r = rhs(ws);
  return lhs(r);
};

/**
 * Extracts the actual word from the text using scope()
 */
const text = (word: string): string => {
  const ws = WordScope(word, Optional.none(), Optional.none());
  const r = scope(ws);
  return r.word;
};

export {
  scope,
  text
};
