////
/// @group utils.json
////

/// Encode any sass value as a JSON-ready string.
///
/// @param {*} $value The scss data to be encoded for JSON exporting

@function encode($value) {
    $type: type-of($value);

    @if ($type == 'bool') {
        @return $value;
    } @else if ($type == 'null') {
        @return 'null';
    } @else if ($type == 'list') {
        @return encode-list($value);
    } @else if ($type == 'map') {
        @return encode-map($value);
    } @else if ($type == 'number') {
        @return encode-number($value);
    }

    @return quotes($value);
}

/// Encode each item in a Sass list, and convert to a JSON-ready
/// square-bracketed list.
///
/// @param {list} $list - List to be encoded for JSON exporting

@function encode-list($list) {
    $str: '';

    @each $item in $list {
        $str: if($str != '', $str + ', ', $str);
        $str: $str + encode($item);
    }

    @return '[#{$str}]';
}

/// Encode each key/value in a Sass map, and convert to a JSON-ready object.
///
/// @param {map} $map - Map to be encoded for JSON exporting

@function encode-map($map) {
    $str: '';

    @each $key, $value in $map {
        $str: if($str != '', $str + ', ', $str);
        $str: $str + quotes($key) + ': ' + encode($value);
    }

    @return '{#{$str}}';
}

/// Encode a number for JSON, adding proof-quotes for length values.
///
/// @param {number} $number - Number to be encoded for JSON exporting

@function encode-number($number) {
    @if unitless($number) {
        @return inspect($number);
    }

    @return quotes($number);
}

/// Convert any value to a double-quoted string.
/// @access private
///
/// @param {*} $value The value to inspect and quote.

@function quotes($value) {
    $value: '#{$value}';
    $value: escape-backslashes($value);
    $value: escape-quotes($value);
    @return '"#{$value}"';
}

/// Return a string, with internal quotes escaped.
/// @access private
///
/// @param {string} $string The string to be manipulated

@function escape-quotes($string) {
    $return: $string;
    $old: '"';
    $new: '\\"';
    $i: str-index($string, $old);
    $n: str-length($old);

    @if ($string == $old) {
        $return: $new;
    } @else if $i {
        $a: if($i > 1, str-slice($string, 1, $i - 1), '');
        $z: str-slice($string, $i + $n);
        $z: escape-quotes($z);

        $return: $a + if($new, $new, '') + $z;
    }

    @return $return;
}

/// Return a string, with internal backslashes escaped.
/// @access private
///
/// @param {string} $string - The string to be manipulated

@function escape-backslashes($string) {
    $return: $string;
    $old: '\\';
    $new: '\\\\';
    $i: str-index($string, $old);
    $n: str-length($old);

    @if ($string == $old) {
        $return: $new;
    } @else if $i {
        $a: if($i > 1, str-slice($string, 1, $i - 1), '');
        $z: str-slice($string, $i + $n);
        $z: escape-backslashes($z);

        $return: $a + if($new, $new, '') + $z;
    }

    @return $return;
}
