'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.toKana = toKana;
exports.splitIntoKana = splitIntoKana;

var _constants = require('./constants');

var _isCharInRange = require('./utils/isCharInRange');

var _isCharInRange2 = _interopRequireDefault(_isCharInRange);

var _isCharUpperCase = require('./utils/isCharUpperCase');

var _isCharUpperCase2 = _interopRequireDefault(_isCharUpperCase);

var _getChunkSize = require('./utils/getChunkSize');

var _getChunkSize2 = _interopRequireDefault(_getChunkSize);

var _getChunk = require('./utils/getChunk');

var _getChunk2 = _interopRequireDefault(_getChunk);

var _isCharConsonant = require('./utils/isCharConsonant');

var _isCharConsonant2 = _interopRequireDefault(_isCharConsonant);

var _isCharVowel = require('./utils/isCharVowel');

var _isCharVowel2 = _interopRequireDefault(_isCharVowel);

var _hiraganaToKatakana = require('./utils/hiraganaToKatakana');

var _hiraganaToKatakana2 = _interopRequireDefault(_hiraganaToKatakana);

var _isKana = require('./isKana');

var _isKana2 = _interopRequireDefault(_isKana);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

/**
 * Convert [Romaji](https://en.wikipedia.org/wiki/Romaji) to [Kana](https://en.wikipedia.org/wiki/Kana), lowercase text will result in [Hiragana](https://en.wikipedia.org/wiki/Hiragana) and uppercase text will result in [Katakana](https://en.wikipedia.org/wiki/Katakana).
 * @param  {String} [input=''] text
 * @param  {DefaultOptions} [options=defaultOptions]
 * @return {String} converted text
 * @example
 * toKana('onaji BUTTSUUJI')
 * // => 'おなじ ブッツウジ'
 * toKana('ONAJI buttsuuji')
 * // => 'オナジ ぶっつうじ'
 * toKana('座禅‘zazen’スタイル')
 * // => '座禅「ざぜん」スタイル'
 * toKana('batsuge-mu')
 * // => 'ばつげーむ'
 * toKana('!?.:/,~-‘’“”[](){}') // Punctuation conversion
 * // => '！？。：・、〜ー「」『』［］（）｛｝'
 * toKana('we', { useObsoleteKana: true })
 * // => 'ゑ'
 */
function toKana() {
  var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
  var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};

  // just throw away the substring index information and just concatenate all the kana
  return splitIntoKana(input, options).map(function (kanaToken) {
    return kanaToken[2];
  }).join('');
}

function splitIntoKana() {
  var input = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
  var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};

  var config = Object.assign({}, _constants.DEFAULT_OPTIONS, options);
  // Final output array containing arrays [start index of the translitterated substring, end index, kana]
  var kana = [];
  // Position in the string that is being evaluated
  var cursor = 0;
  var len = input.length;
  var maxChunk = 3;
  var chunkSize = 3;
  var chunk = '';
  var chunkLC = '';

  // Steps through the string pulling out chunks of characters. Each chunk will be evaluated
  // against the romaji to kana table. If there is no match, the last character in the chunk
  // is dropped and the chunk is reevaluated. If nothing matches, the character is assumed
  // to be invalid or punctuation or other and gets passed through.
  while (cursor < len) {
    var kanaChar = null;
    chunkSize = (0, _getChunkSize2.default)(maxChunk, len - cursor);
    while (chunkSize > 0) {
      chunk = (0, _getChunk2.default)(input, cursor, cursor + chunkSize);
      chunkLC = chunk.toLowerCase();
      // Handle super-rare edge cases with 4 char chunks (like ltsu, chya, shya)
      if (_constants.FOUR_CHAR_EDGECASES.includes(chunkLC) && len - cursor >= 4) {
        chunkSize += 1;
        chunk = (0, _getChunk2.default)(input, cursor, cursor + chunkSize);
        chunkLC = chunk.toLowerCase();
      } else {
        // Handle edge case of n followed by consonant
        if (chunkLC.charAt(0) === 'n') {
          if (chunkSize === 2) {
            // Handle edge case of n followed by a space (only if not in IME mode)
            if (!config.IMEMode && chunkLC.charAt(1) === ' ') {
              kanaChar = 'ん ';
              break;
            }
            // Convert IME input of n' to "ん"
            if (config.IMEMode && chunkLC === "n'") {
              kanaChar = 'ん';
              break;
            }
          }
          // Handle edge case of n followed by n and vowel
          if ((0, _isCharConsonant2.default)(chunkLC.charAt(1), false) && (0, _isCharVowel2.default)(chunkLC.charAt(2))) {
            chunkSize = 1;
            chunk = (0, _getChunk2.default)(input, cursor, cursor + chunkSize);
            chunkLC = chunk.toLowerCase();
          }
        }

        // Handle case of double consonants
        if (chunkLC.charAt(0) !== 'n' && (0, _isCharConsonant2.default)(chunkLC.charAt(0)) && chunk.charAt(0) === chunk.charAt(1)) {
          chunkSize = 1;
          // Return katakana ッ if chunk is uppercase, otherwise return hiragana っ
          if ((0, _isCharInRange2.default)(chunk.charAt(0), _constants.UPPERCASE_START, _constants.UPPERCASE_END)) {
            chunkLC = 'ッ';
            chunk = 'ッ';
          } else {
            chunkLC = 'っ';
            chunk = 'っ';
          }
        }
      }

      kanaChar = _constants.FROM_ROMAJI[chunkLC];
      // console.log(`${chunkLC}, ${cursor}x${chunkSize}:${chunk} => ${kanaChar}`); // DEBUG
      if (kanaChar != null) {
        break;
      }
      // Step down the chunk size.
      // If chunkSize was 4, step down twice.
      if (chunkSize === 4) {
        chunkSize -= 2;
      } else {
        chunkSize -= 1;
      }
    }

    // Passthrough undefined values
    if (kanaChar == null) {
      kanaChar = chunk;
    }

    // Handle special cases.
    if (config.useObsoleteKana) {
      if (chunkLC === 'wi') kanaChar = 'ゐ';
      if (chunkLC === 'we') kanaChar = 'ゑ';
    }

    if (!!config.IMEMode && chunkLC.charAt(0) === 'n') {
      if (input.charAt(cursor + 1).toLowerCase() === 'y' && (0, _isCharVowel2.default)(input.charAt(cursor + 2)) === false || cursor === len - 1 || (0, _isKana2.default)(input.charAt(cursor + 1))) {
        // Don't transliterate this yet.
        kanaChar = chunk.charAt(0);
      }
    }

    // Use katakana if first letter in chunk is uppercase
    if ((0, _isCharUpperCase2.default)(chunk.charAt(0))) {
      kanaChar = (0, _hiraganaToKatakana2.default)(kanaChar);
    }

    var nextCursor = cursor + (chunkSize || 1);
    kana.push([cursor, nextCursor, kanaChar]);
    cursor = nextCursor;
  }
  return kana;
}

exports.default = toKana;