//@include lib_Class.js

/**
 * This class contains convinience methods for working with strings.
 *
 * Works transparently with Java and JavaScript Strings
 *
 * @author PZ, ELO Digital Office GmbH
 * @version 1.0
 *
 * @eloall
 */
sol.define("sol.common.StringUtils", {
  singleton: true,

  /**
   * Returns a formatted string.
   * The first parameter contains the String which should be formatted.
   * This parameter is followed by an arbitary number uf strings, which will be used to replace the placefolders.
   *
   * # Examples
   *
   *     sol.common.StringUtils.format("Hello {0}!", "world");
   *
   *     sol.common.StringUtils.format("An error occurred writing object {0} to database. Exception was: {1}", objId, ex);
   *
   *     sol.common.StringUtils.format("Value of {0} updated: {1} -> {2}", key, oldValue, newValue);
   *
   * @param {String} str String which should be formated, containing placeholders
   * @return {String}
   */
  format: function (str) {
    var args = Array.prototype.slice.call(arguments, 1);

    return str.replace(/\{(\d+)\}/g, function (match, number) {
      return (typeof args[number] !== "undefined") ? args[number] : match;
    });
  },

  /**
   * Checks, if a string starts with another string
   * @param {String} str
   * @param {String} pattern
   * @returns {Boolean}
   */
  startsWith: function (str, pattern) {
    return str.indexOf(pattern) === 0;
  },

  /**
   * Checks, if a string ends with another string
   * @param {String} str
   * @param {String} pattern
   * @returns {Boolean}
   */
  endsWith: function (str, pattern) {
    var postfixLength;
    str += "";
    pattern += "";
    postfixLength = (pattern.length < str.length) ? pattern.length : str.length;
    return str.indexOf(pattern) === (str.length - postfixLength);
  },

  /**
   * Checks, if a string contains another string
   * @param {String} str
   * @param {String} pattern
   * @returns {Boolean}
   */
  contains: function (str, pattern) {
    return str.indexOf(pattern) !== -1;
  },

  /**
   * Checks, if a string has a numeric value
   * @param {String} str
   * @returns {Boolean}
   */
  isNumeric: function (str) {
    return (!isNaN(parseFloat(str)) && isFinite(str));
  },

  /**
   * Checks, if a string is not defined/null or empty
   * @param {String} str
   * @returns {Boolean}
   */
  isEmpty: function (str) {
    if (!str) {
      return true;
    }
    str += "";
    return (str.length <= 0);
  },

  /**
   * Checks, if a string is not defined/null, empty or contains only whitespaces
   * @param {String} str
   * @returns {Boolean}
   */
  isBlank: function (str) {
    return !str || this.isEmpty(str.trim());
  },

  /**
   * Pads a string at the left side
   * @param {String|Number} str Input string
   * @param {Number} length Destination length of the string
   * @param {String} [padString="0"] (optional) Padding string
   * @return {String} Padded string
   */
  padLeft: function (str, length, padString) {
    str += "";
    padString = padString || "0";
    while (str.length < length) {
      str = padString + str;
    }
    return str;
  },

  /**
   * Pads a string at the right side
   * @param {String|Number} str Input string
   * @param {Number} length Destination length of the string
   * @param {String} [padString="0"] (optional) Padding string
   * @return {String} Padded string
   */
  padRight: function (str, length, padString) {
    str += "";
    padString = padString || "0";
    while (str.length < length) {
      str += padString;
    }
    return str;
  },

  /**
   * Replaces every occurrence of a substring with another string
   * @param {String} str Input string
   * @param {String} target String to replace
   * @param {String} replacement Replacement string
   * @returns {String} Padded string
   */
  replaceAll: function (str, target, replacement) {
    return String(str).split(target).join(replacement);
  },

  /**
   * Returns the trailing number string
   * @param {String} str Input string
   * @return {String} Number string
   */
  getTrailingNumber: function (str) {
    var match = String(str).match(/\d+$/);
    if (match && (match.length > 0)) {
      return parseInt(match[0], 10);
    }
  },

  /**
   * Removes the trailing number
   * @param {String} str Input string
   * @return {String} Number string
   */
  removeTrailingNumber: function (str) {
    return String(str).replace(/\d+$/, "");
  },

  /**
   * Removes line breaks
   * @param {String} str Input string
   * @param {Object} config Configuration
   * @param {String} config.replaceString Replace string
   * @return {String}
   */
  replaceLineBreaks: function (str, config) {
    config = config || {};
    config.replaceString = config.replaceString || " ";
    return String(str).replace(/\r?\n|\r/g, config.replaceString);
  },

  /**
   * Splits a string into lines
   * @param {String} text Text
   * @return {Array} lines
   */
  splitLines: function (text) {
    var lines;
    text = text || "";
    lines = text.split(/\r\n|\n|\r/);
    return lines;
  },

  /**
   * Parses an INI string
   * @param {String} iniString INI file content
   * @return {Object} Object
   */
  parseIniString: function (iniString) {
    var regex,
        obj = {},
        lines, section, match;

    regex = {
      section: /^\s*\[\s*([^\]]*)\s*\]\s*$/,
      param: /^\s*([^=]+?)\s*=\s*(.*?)\s*$/,
      comment: /^\s*;.*$/
    };

    lines = iniString.split(/[\r\n]+/);
    lines.forEach(function (line) {
      if (!regex.comment.test(line)) {
        if (regex.param.test(line)) {
          match = line.match(regex.param);
          if (section) {
            obj[section][match[1]] = match[2];
          } else {
            obj[match[1]] = match[2];
          }
        } else if (regex.section.test(line)) {
          match = line.match(regex.section);
          obj[match[1]] = {};
          section = match[1];
        } else if (line.length == 0 && section) {
          section = null;
        }
      }
    });
    return obj;
  },

  /**
   * Remove quotes
   * @param {String} str
   * @return {String} String without quotes
   */
  removeQuotes: function (str) {
    var firstChar, lastChar;
    str += "";
    if (str && (str.length > 1)) {
      firstChar = str.charAt(0);
      lastChar = str.charAt(str.length - 1);
      if ((firstChar == '"' && lastChar == '"') || (firstChar == "'" && lastChar == "'")) {
        if (str.length > 2) {
          str = str.substr(1, str.length - 2);
        } else {
          str = "";
        }
      }
    }
    return str;
  },

  /**
   * @protected
   * Truncates a string to the appropriate length
   * maxlength is the total length from the string to be shortened plus the length of the suffix.
   *
   * That means with the default suffix "...", the original str will be shorten earlier as expected.
   * Example:
   * For the result: "Hello..." you have to call the truncate function in this way
   * sol.common.StringUtils.truncate("Hello World", 8)
   *
   * If you want to skip ellipsies at the end, you can call
   * `sol.common.StringUtils.truncate("Hello World", 5, { suffix: "" })`
   *
   * This result in the str `Hello` without any suffix. This is the same like substr(0, 5)
   * @param {String} str the string to truncate
   * @param {String|Number} maxLength
   * @param {Object} options
   * @param {String} options.suffix Appending to the truncate str.
   * @return {String} truncate string. If str is shorter than maxLength - suffix.length than the same str will be return
   */
  truncate: function (str, maxLength, options) {
    var opt = options || {},
      resultLength = maxLength || 0;

    if (resultLength <= 0 || isNaN(resultLength)) {
      throw Error("maxLength must be a positive number > 0, maxLength=" + resultLength);
    }

    // Checks whether opt has an property called "suffix"
    // We could not use opt.suffix || "..." statement here
    // because opt.suffix = "" is in javascript always false
    opt.suffix = "suffix" in opt
      ? opt.suffix
      : "...";

    str = (str) ? String(str) : str;

    if (str && (str.length > resultLength)) {
      str = str.substring(0, resultLength - opt.suffix.length) + opt.suffix;
    }

    return str;
  }
});

//# sourceURL=lib_sol.common.StringUtils.js