////
/// Parsing engine
/// @author Kitty Giraudel
/// @access private
////

///
/// Get operator of an expression
///
/// @param {String} $expression - Expression to extract operator from
///
/// @return {String} - Any of `>=`, `>`, `<=`, `<`, `≥`, `≤`
///
@function get-expression-operator($expression) {
  @each $operator in ('>=', '>', '<=', '<', '≥', '≤') {
    @if string.index($expression, $operator) {
      @return $operator;
    }
  }

  // It is not possible to include a mixin inside a function, so we have to
  // rely on the `im-log(..)` function rather than the `log(..)` mixin. Because
  // functions cannot be called anywhere in Sass, we need to hack the call in
  // a dummy variable, such as `$_`. If anybody ever raise a scoping issue with
  // Sass 3.3, change this line in `@if im-log(..) {}` instead.
  $_: im-log('No operator found in `#{$expression}`.');
}

///
/// Get dimension of an expression, based on a found operator
///
/// @param {String} $expression - Expression to extract dimension from
/// @param {String} $operator - Operator from `$expression`
///
/// @return {String} - `width` or `height` (or potentially anything else)
///
@function get-expression-dimension($expression, $operator) {
  $operator-index: string.index($expression, $operator);
  $parsed-dimension: string.slice($expression, 0, $operator-index - 1);
  $dimension: 'width';

  @if string.length($parsed-dimension) > 0 {
    $dimension: $parsed-dimension;
  }

  @return $dimension;
}

///
/// Get dimension prefix based on an operator
///
/// @param {String} $operator - Operator
///
/// @return {String} - `min` or `max`
///
@function get-expression-prefix($operator) {
  @return if(list.index(('<', '<=', '≤'), $operator), 'max', 'min');
}

///
/// Get value of an expression, based on a found operator
///
/// @param {String} $expression - Expression to extract value from
/// @param {String} $operator - Operator from `$expression`
///
/// @return {Number} - A numeric value
///
@function get-expression-value($expression, $operator) {
  $operator-index: string.index($expression, $operator);
  $value: string.slice($expression, $operator-index + string.length($operator));

  @if map.has-key($breakpoints, $value) {
    $value: map.get($breakpoints, $value);
  } @else {
    $value: to-number($value);
  }

  $interval: map.get($unit-intervals, math.unit($value));

  @if not $interval {
    // It is not possible to include a mixin inside a function, so we have to
    // rely on the `im-log(..)` function rather than the `log(..)` mixin. Because
    // functions cannot be called anywhere in Sass, we need to hack the call in
    // a dummy variable, such as `$_`. If anybody ever raise a scoping issue with
    // Sass 3.3, change this line in `@if im-log(..) {}` instead.
    $_: im-log('Unknown unit `#{math.unit($value)}`.');
  }

  @if $operator == '>' {
    $value: $value + $interval;
  } @else if $operator == '<' {
    $value: $value - $interval;
  }

  @return $value;
}

///
/// Parse an expression to return a valid media-query expression
///
/// @param {String} $expression - Expression to parse
///
/// @return {String} - Valid media query
///
@function parse-expression($expression) {
  // If it is part of $media-expressions, it has no operator
  // then there is no need to go any further, just return the value
  @if map.has-key($media-expressions, $expression) {
    @return map.get($media-expressions, $expression);
  }

  $operator: get-expression-operator($expression);
  $dimension: get-expression-dimension($expression, $operator);
  $prefix: get-expression-prefix($operator);
  $value: get-expression-value($expression, $operator);

  @return '(#{$prefix}-#{$dimension}: #{$value})';
}
