/// Parse CQ
///
/// @param {map} $map - The map from which to parse CQ
/// @param {bool} $sub-component
/// @param {bool} $prevContext
@mixin parse-cq($map, $sub-component: false, $prevContext: false) {
  @each $property, $value in $map {
    @if type-of($property) == 'string' {
      // $property defines new Modifier
      @if str-index($property, 'modifier(') == 1 or str-index($property, $modifierGlue) == 1 {
        @include modifier(get-param($property)) {
          @include parse-cq($value);
        }
      }

      // $property defines new Component
      @else if str-index($property, 'component(') == 1 or str-index($property, $componentGlue) == 1 {
        @include component(get-param($property)) {
          @include parse-cq($value);
        }
      }

      // $property defines new Component
      @else if str-index($property, 'sub-component(') == 1 {
        @include sub-component(get-param($property)) {
          @include parse-cq($value);
        }
      }

      // $property is for parent wrapper/group element
      @else if $property == 'group' or $property == 'wrapper' {
        @include wrapper($property, if($prevContext, $prevContext, $module)) {
          @include parse-cq($value);
        }
      }

      // Determine if current node is queried modifier/state
      @else if str-index($property, 'is-') == 1 {
        @include modifier(str-replace($property, 'is-', '')) {
          @include parse-cq($value);
        }
      }

      // Determine if parent module/block is queried modifier/state
      @else if str-index($property, '$-is-') == 1 or str-index($property, '$:') == 1 {
        $context: if(str-index($property, '$:') == 1, str-replace($property, '$', ''), str-replace($property, '$-is-', ''));

        @include context($module, $context) {
          @include parse-cq($value, $prevContext: ($module, $context));
        }
      }

      // Determine if previously specified parent component is queried modifier/state
      @else if str-index($property, 'and-is-') == 1 or str-index($property, 'and:') == 1 {
        $context: if(
          str-index($property, 'and-is-'),
          str-replace($property, 'and-is-', ''),
          str-slice($property, str-index($property, ':'), str-length($property))
        );
        $prevContextVal: ('block': nth($prevContext, 1), 'context': nth($prevContext, 2));
        $prevChunk: create-selector-from-context(map-get($prevContextVal, 'block'), map-get($prevContextVal, 'context'));
        $newContextVal: append(map-get($prevContextVal, 'context'), $context);
        $newChunk: create-selector-from-context(map-get($prevContextVal, 'block'), $newContextVal, $pipeContexts: true);

        $selector: ();

        @each $pChunk in $prevChunk {
          @each $chunk in selector-parse(str-replace(inspect($newChunk), ' ', ', ')) {
            @if str-index(inspect($chunk), $pChunk) == 1 {
              @each $item in & {
                @if str-index(inspect($item), $pChunk) {
                  $selector: append($selector, selector-replace($item, $pChunk, $chunk), comma);
                }
              }
            }
          }
        }

        @at-root {
          #{$selector} {
            @include parse-cq($value, $prevContext: (map-get($prevContextVal, 'block'), $newContextVal));
          }
        }
      }

      // Determine if specified parent component/module is queried modifier/state
      @else if str-index($property, '-is-') or (str-index($property, ':') and str-index($property, ':') > 1) {
        $component: if(
          str-index($property, ':'),
          str-slice($property, 1, str-index($property, ':') - 1),
          str-slice($property, 1, str-index($property, '-is-') - 1)
        );
        $contextVal: if(
          str-index($property, ':'),
          str-slice($property, str-index($property, ':'), str-length($property)),
          str-slice($property, str-index($property, '-is-') + 4, str-length($property))
        );
        $block: if(str-index($component, '$') == 1, str-slice($component, 2), $module);
        $context: if(str-index($component, '$') == 1, ($block, $contextVal), (($block, $component), $contextVal));

        @if $component == 'group' or $component == 'wrapper' {
          $context: ($component, ($prevContext, $contextVal), true);
        }

        @include context($context...) {
          @include parse-cq($value, $prevContext: $context);
        }
      }

      // Determine if current node is a child of the queried component/module
      @else if str-index($property, 'in-') == 1 {
        $component: str-replace($property, 'in-', '');
        $context: if(str-index($component, '$') == 1, str-slice($component, 2), ($module, $component));

        @include context($context) {
          @include parse-cq($value, $prevContext: ($context, ''));
        }
      }

      // $property defines pseudo-state/pseudo-element
      @else if str-index($property, ':') == 1 {
        @include pseudo-state(str-replace($property, ':', '')) {
          @include parse-cq($value);
        }
      }

      // $property defines .active styles
      @else if $property == 'active' {
        @include modifier('active') {
          @include parse-cq($value);
        }
      }

      // $property is for a component
      @else if type-of($value) == 'map' {
        @include component($property, $sub-component: $sub-component) {
          @include parse-cq($value, $sub-component: true, $prevContext: $property);
        }
      }

      // $property is a valid CSS property
      @else if index($css-properties, $property) {
        @if type-of($value) != 'map' {
          // for before/after pseudo elements
          @if $property == 'content' {
            $value: '"#{$value}"';
          }

          #{$property}: $value;
        }
      }
    }
  }
}