import {CoreType} from "./Type";
import {ArrayUtils as ArrayUtils2} from "./ArrayUtils";
const ATTRIB_NAMES_SEPARATOR = /[, ]/;
const TAIL_DIGIT_MATCH_REGEXP = /\d+$/;
const LEADING_ZEROS_MATCH_REGEXP = /^0+/;
const INDICES_LIST_SEPARATOR = /,| /;
const ZERO = "0";
const SPACE = " ";
const NUM_REGEXP = /^-?\d+\.?\d*$/;
var BooleanString;
(function(BooleanString2) {
  BooleanString2["TRUE"] = "true";
  BooleanString2["FALSE"] = "false";
})(BooleanString || (BooleanString = {}));
export class CoreString {
  static isBoolean(word) {
    return word == BooleanString.TRUE || word == BooleanString.FALSE;
  }
  static toBoolean(word) {
    return word == BooleanString.TRUE;
  }
  static isNumber(word) {
    return NUM_REGEXP.test(word);
  }
  static tailDigits(word) {
    const match = word.match(TAIL_DIGIT_MATCH_REGEXP);
    if (match) {
      return parseInt(match[0]);
    } else {
      return 0;
    }
  }
  static increment(word) {
    const match = word.match(TAIL_DIGIT_MATCH_REGEXP);
    if (match) {
      let numbers_as_str = match[0];
      let zeros_prefix = "";
      const leading_zeros_match = numbers_as_str.match(LEADING_ZEROS_MATCH_REGEXP);
      if (leading_zeros_match) {
        zeros_prefix = leading_zeros_match[0];
      }
      const digits = parseInt(numbers_as_str);
      if (digits == 0) {
        if (zeros_prefix.length > 0) {
          if (zeros_prefix[zeros_prefix.length - 1] == ZERO) {
            zeros_prefix = zeros_prefix.slice(0, -1);
          }
        }
      }
      const prefix = word.substring(0, word.length - match[0].length);
      return `${prefix}${zeros_prefix}${digits + 1}`;
    } else {
      return `${word}1`;
    }
  }
  static pluralize(word) {
    const last_char = word[word.length - 1];
    if (last_char !== "s") {
      return `${word}s`;
    } else {
      return word;
    }
  }
  static camelCase(str) {
    const elements = str.replace(/_/g, " ").split(" ");
    let newWord = "";
    for (let i = 0; i < elements.length; i++) {
      let element = elements[i].toLowerCase();
      if (i > 0) {
        element = this.upperFirst(element);
      }
      newWord += element;
    }
    return newWord;
  }
  static upperFirst(word) {
    const newString = word[0].toUpperCase() + word.substr(1);
    return newString;
  }
  static titleize(word) {
    const elements = word.split(/\s|_/g);
    const newElements = elements.map((elem) => this.upperFirst(elem));
    return newElements.join(" ");
  }
  static precision(val, decimals = 2) {
    decimals = Math.max(decimals, 0);
    const elements = `${val}`.split(".");
    if (decimals <= 0) {
      return elements[0];
    }
    let frac = elements[1];
    if (frac !== void 0) {
      if (frac.length > decimals) {
        frac = frac.substring(0, decimals);
      }
      frac = frac.padEnd(decimals, "0");
      return `${elements[0]}.${frac}`;
    } else {
      const string_to_pad = `${val}.`;
      const pad = string_to_pad.length + decimals;
      return string_to_pad.padEnd(pad, "0");
    }
  }
  static ensureFloat(num) {
    const num_as_string = `${num}`;
    const dot_pos = num_as_string.indexOf(".");
    if (dot_pos >= 0) {
      return num_as_string;
    } else {
      return `${num_as_string}.0`;
    }
  }
  static matchMask(word, mask) {
    if (mask === "*") {
      return true;
    }
    if (word == mask) {
      return true;
    }
    const elements = mask.split(SPACE);
    if (elements.length > 1) {
      for (let element of elements) {
        const match = this.matchMask(word, element);
        if (match) {
          return true;
        }
      }
      return false;
    }
    mask = mask.split("*").join(".*");
    mask = `^${mask}$`;
    const regex = new RegExp(mask);
    return regex.test(word);
  }
  static matchesOneMask(word, masks) {
    let matches_one_mask = false;
    for (let mask of masks) {
      if (CoreString.matchMask(word, mask)) {
        matches_one_mask = true;
      }
    }
    return matches_one_mask;
  }
  static attribNames(word) {
    const elements = word.split(ATTRIB_NAMES_SEPARATOR);
    const names_set = new Set();
    for (let element of elements) {
      element = element.trim();
      if (element.length > 0) {
        names_set.add(element);
      }
    }
    const names = new Array(names_set.size);
    let i = 0;
    names_set.forEach((name) => {
      names[i] = name;
      i++;
    });
    return names;
  }
  static indices(indices_string) {
    const elements = indices_string.split(INDICES_LIST_SEPARATOR);
    if (elements.length > 1) {
      const indices = elements.flatMap((element) => this.indices(element));
      return ArrayUtils2.uniq(indices).sort((a, b) => a - b);
    } else {
      const element = elements[0];
      if (element) {
        const range_separator = "-";
        if (element.indexOf(range_separator) > 0) {
          const range_elements = element.split(range_separator);
          return ArrayUtils2.range(parseInt(range_elements[0]), parseInt(range_elements[1]) + 1);
        } else {
          const parsed = parseInt(element);
          if (CoreType.isNumber(parsed)) {
            return [parsed];
          } else {
            return [];
          }
        }
      } else {
        return [];
      }
    }
  }
  static escapeLineBreaks(word) {
    return word.replace(/(\r\n|\n|\r)/gm, "\\n");
  }
}
