'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

var sqlite = require('@themost/sqlite');
var query = require('@themost/query');
var path = require('path');
require('@themost/common');

function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }

var path__default = /*#__PURE__*/_interopDefaultLegacy(path);

class WordFinder {
  constructor() {
    this.db = new sqlite.SqliteAdapter({
      database: path__default["default"].resolve(__dirname, '../db/words.db')
    });
    this.options = {
      maxWords: 100
    };
  }
  /**
   * The operation will try to find the given string in the dictionary
   * @param {string} str 
   * @returns Returns a promise that will be resolved with the given string if it is found in the dictionary
   */
  async find(str) {
    return this.db.executeAsync(new query.QueryExpression().select(new query.QueryField('word')).from('WordBase').where('word').equal(str)).then(([result]) => {
      return result && result.word;
    });
  }

  /**
   * The operation will try to split the given string into words that are found in the dictionary
   * e.g. 'calendartype' will be split into 'calendar' and 'type'.
   * @param {*} str 
   * @returns {Promise<string[]>} The operation will return an array of strings that are found in the dictionary
   */
  async trySplit(str) {
    let word = str;
    let results = [];
    let continueProcessing = true;
    while (continueProcessing) {
      let args = [];
      let index = 1;
      while (index < word.length) {
        args.push(word.substring(0, index + 1).toLowerCase());
        index++;
      }
      let argIndex = 0;
      let findWords = await this.db.executeAsync(new query.QueryExpression().select(new query.QueryField('word')).from('WordBase').where('word').equal(args));
      for (const arg of args.reverse()) {
        let findWord = findWords.find(item => item.word === arg);
        if (findWord) {
          const re = new RegExp(`^${arg}`, 'i');
          word = word.replace(re, '');
          results.push(arg);
          break;
        }
        argIndex++;
      }
      continueProcessing = word.length > 0 && argIndex < args.length;
    }
    return results;
  }

  /**
   * The operation will try to find words that starts with the given array of strings
   * @param {...string} str An array of strings to search for
   * @returns {Promise<string[]>} Returns a promise that will be resolved with an array of strings that are found in the dictionary
   */
  async startsWith(str) {
    const args = Array.from(arguments);
    const q = new query.QueryExpression().select(new query.QueryField('word')).from('WordBase').take(this.options.maxWords);
    if (args.length > 0) {
      for (let i = 0; i < args.length; i++) {
        if (i === 0) {
          q.where('word').startsWith(args[i]);
        } else {
          q.or('word').startsWith(args[i]);
        }
      }
    } else {
      q.where('word').equal(null);
    }
    q.orderByDescending(new query.QueryField('word'));
    return this.db.executeAsync(q).then(results => {
      return results.map(result => result.word);
    });
  }
}

class FieldNaming {
  constructor(options) {
    this.wordFinder = new WordFinder();
    this.options = Object.assign({
      separator: '',
      camelCase: true,
      exclude: []
    }, options);
  }
  async format(str) {
    if (this.options.exclude.indexOf(str) !== -1) {
      return str;
    }
    const results = await this.wordFinder.trySplit(str.replace(/_/g, ''));
    if (results.length > 0) {
      // if (results.length > 1 && results[results.length - 1] === 'id') {
      //     results.pop();
      // }
      return results.map((item, index) => {
        if (this.options.camelCase) {
          if (index === 0) {
            return item;
          }
          return item.charAt(0).toUpperCase() + item.slice(1);
        }
        return item;
      }).join(this.options.separator);
    }
    return str;
  }

  /**
   * The operation will format an array of fields
   */
  async formatMany(field) {
    const fields = Array.from(arguments);
    const results = [];
    for (const field of fields) {
      let name = await this.format(field);
      results.push(name);
    }
    return results;
  }
}

exports.FieldNaming = FieldNaming;
exports.WordFinder = WordFinder;
//# sourceMappingURL=index.js.map
