// str-split function
// --------------------------
/// Split a string by a given string into a list.
/// @access public
/// @group string utilities
/// @type String
/// @output List
/// @parameter String String

@function str-split($str, $separator) {
  // empty array/list
  $split-arr: ();
  // // first index of separator in str
  $index: str-index($str, $separator);
  // loop through str
  @while $index != null {
    // get the substr from the first character to the separator
    $item: str-slice($str, 1, $index - 1);
    // push item to array
    $split-arr: append($split-arr, $item);
    // remove item and separator from str
    $str: str-slice($str, $index + 1);
    // find new index of separator
    $index: str-index($str, $separator);
  }
  // add the remaining str to list (the last item)
  $split-arr: append($split-arr, $str);

  @return $split-arr;
}

// str-splice function
// --------------------------
/// Split a string by a given string into a list.
/// @access public
/// @group string utilities
/// @alias str-split

@function str-splice($str, $separator) {
  @return str-split($str, $separator);
}

// str-replace function
// --------------------------
/// Split a string by a given string into a list.
/// @access public
/// @group string utilities
/// @type String
/// @output String
/// @parameter String String

// Make str replace accept lists.
@function str-replace($haystack, $needles, $replacers: "") {
  // Check if the $needle argument is a list and based of that
  // go through the list replace all instances.
  // Also check if both needle and haystack are lists. If the list are the same length,
  // All items in the haystack will be replaced with all items in the needles.

  @if length($needles) == 1 {
    $needles: list-to-str($needles);
  }
  @if length($replacers) == 1 {
    $replacers: list-to-str($replacers);
  }

  @if type-of($needles) == "list" and type-of($replacers) == "list" {
    @if length($needles) == length($replacers) {
      // Check if the $needle argument is a string or a list and based of that
      // go through the list or string to replace all instances.
      @for $i from 1 through length($needles) {
        @if str-contains($haystack, nth($needles, $i)) {
          $haystack: str-replace-func(
            $haystack,
            nth($needles, $i),
            nth($replacers, $i)
          );
        }
      }
    } @else {
      @if type-of($replacers) == "list" {
        $replacers: list-to-str($replacers);
      }
      @for $i from 1 through length($needles) {
        @if str-contains($haystack, nth($needles, $i)) {
          $haystack: str-replace-func($haystack, nth($needles, $i), $replacers);
        }
      }
      @return $haystack;
    }
    @return $haystack;
  }
  // If only the needle is a list, just replace all instance of the
  // strings in this list with the default replacer.
  @else if type-of($needles) == "list" {
    @each $needles in $needles {
      @if type-of($replacers) == "list" {
        $replacers: list-to-str($replacers);
      }
      $haystack: str-replace-func($haystack, $needles, $replacers);
    }
    @return $haystack;
  }
  // If $needle and haystack are normal strings, just find the needles
  // and replace those.
  @else {
    @return str-replace-func($haystack, $needles, $replacers);
  }
}

// str-replace-func function
// --------------------------
/// The actual replacing function used in str-replace
/// @access public
/// @group string utilities
/// @type String
/// @output String
/// @parameter String

// The str replace function
@function str-replace-func($haystack, $needle, $replace: "") {
  // First make sure needle nor haystack are empty values;
  @if $needle == " " {
    $index: str-index($haystack, $needle);
    @if $index {
      @return str-slice($haystack, 1, $index - 1) + $replace +
        str-replace(
          str-slice($haystack, $index + str-length($needle)),
          $needle,
          $replace
        );
    }
  }

  @if type-of($haystack) == null or type-of($needle) == null {
    @return $haystack;
  } @else {
    // And check if the needle and haystack are actually strs, otherwise warn.
    @if type-of($haystack) == "string" and type-of($needle) == "string" {
      $index: str-index($haystack, $needle);
      @if $index {
        @return str-slice($haystack, 1, $index - 1) + $replace +
          str-replace(
            str-slice($haystack, $index + str-length($needle)),
            $needle,
            $replace
          );
      }
    }
    @if type-of($haystack) != "string" {
      @warn '#{$haystack}(#{type-of($haystack)}) is not a str.';
    }
    @if type-of($needle) != "string" {
      @warn '#{$needle}(#{type-of($needle)}) is not a str.';
    }
  }
  @return $haystack;
}

// to-strg function
// --------------------------
/// Convert a value to a string.
/// @access public
/// @group string utilities
/// @type String
/// @output String
/// @parameter String

@function to-str($str) {
  // Check if the value is already a string, if so just return the value
  @if type-of($str) == "string" {
    @return $str;
  }
  // Check if the value will become a string, if you put it in quotes.
  @else if type-of("#{$str}") == "string" {
    @return "#{$str}";
  } @else if $str == false {
    @return "false";
  } @else if $str == true {
    @return "false";
  }
  // If it still won't be a string, just try to throw it back.
  @else {
    @return "#{$str}";
  }
}

@function str-contains($haystack, $needle) {
  @if str-index($haystack, $needle) !=
    null and
    str-index($haystack, $needle) !=
    "" and
    type-of(str-index($haystack, $needle)) !=
    null
  {
    @return true;
  } @else {
    @return false;
  }
}

// dasherize function
// --------------------------
/// Convert a string which can be used as slug
/// @access public
/// @group string utilities
/// @type String
/// @output String
/// @parameter String

@function dasherize($str) {
  $str: str-replace($str, " ", "-");
  $str: str-replace($str, " ", "-");
  $str: allowed-characters(
    to-lower-case(safe-characters($str)),
    ("a-z", "0-9", "-")
  );
  @return $str;
}

// dasherize function
// --------------------------
/// Convert a string and remove special characters. Replace spaces with underscores.
/// @access public
/// @group string utilities
/// @type String
/// @output String
/// @parameter String

@function underscore($str) {
  @return str-replace-func(dasherize($str), "-", "_");
}

// letter-uppercase function
// --------------------------
/// Uppercase one letter in a string, by default the first one.
/// @access public
/// @group string utilities
/// @type String
/// @output String
/// @parameter String

@function letter-uppercase($str, $letter: 1) {
  $new-str: ();
  @if $letter > 1 {
    $new-str: append($new-str, str-slice($str, 1, $letter));
    $new-str: append($new-str, to-upper-case(str-slice($str, $letter, 1)));
    $new-str: append($new-str), str-slice($str, $letter + 1, str-length($str));
  } @else {
    $new-str: append($new-str, to-upper-case(str-slice($str, 1, 1)));
    $new-str: append($new-str, str-slice($str, 2, str-length($str)));
  }
  @return list-to-str($new-str, null);
}

// letter-uppercase function
// --------------------------
/// Uppercase one letter in a string, by default the first one.
/// @access public
/// @group string utilities
/// @type String
/// @output String
/// @parameter String

@function letter-lowercase($str, $letter: 1) {
  $new-str: ();
  @if $letter > 1 {
    $new-str: append($new-str, str-slice($str, 1, $letter));
    $new-str: append($new-str, to-lower-case(str-slice($str, $letter, 1)));
    $new-str: append($new-str), str-slice($str, $letter + 1, str-length($str));
  } @else {
    $new-str: append($new-str, to-lower-case(str-slice($str, 1, 1)));
    $new-str: append($new-str, str-slice($str, 2, str-length($str)));
  }
  @return list-to-str($new-str, null);
}

// str-remove-whitespace function
// --------------------------
/// Removes all whitespaces from string
/// @access public
/// @group string utilities
/// @type String
/// @output String
/// @parameter String

@function str-remove-whitespace($str) {
  @while (str-index($str, " ") != null) {
    $index: str-index($str, " ");
    $str: "#{str-slice($str, 0, $index - 1)}#{str-slice($str, $index + 1)}";
  }
  @return $str;
}

// Trim function
// --------------------------
/// Trim a string
/// @access public
/// @group case utilities
///
/// @parameter String
/// @output String
///

@function trim($str) {
  @if str-slice($str, 1, 1) == " " {
    @return trim(str-slice($str, 2, str-length($str)));
  } @else if str-slice($str, str-length($str), str-length($str)) == " " {
    @return trim(str-slice($str, 1, str-length($str) - 1));
  } @else {
    @return $str;
  }
}
