@use 'sass:list';
@use 'sass:map';
@use 'sass:meta';
@use 'sass:string';
@use '@tokens' as tokens;
@use './alignment';
@use './links';
@use './list' as spirit-list;
@use './placement';
@use './reset';
@use './string' as spirit-string;
@use './typography';

// Mixin to generate alignment classes based on a dictionary
// Parameters are:
// * $class-name: the name of the component class to generate
// * $dictionary-values: map of the dictionary values to generate
// * $axis: the axis to generate, either 'x' or 'y'
// * $property: the CSS property to apply the alignment to (for the x-axis only)
// * $infix: the infix to add to the class name
@mixin generate-alignments($class-name, $dictionary-values, $axis, $property: 'justify-content', $infix: '') {
    $prefix: spirit-string.convert-pascal-case-to-kebab-case($class-name);

    @each $alignment in $dictionary-values {
        .#{$class-name}--#{$infix}#{spirit-string.convert-kebab-case-to-camel-case(alignment-#{$axis}-#{$alignment})} {
            @if $axis == 'x' {
                #{$property}: string.unquote(alignment.translate-physical-to-logical($alignment));
            } @else {
                align-items: string.unquote(alignment.translate-physical-to-logical($alignment));
            }
        }
    }
}

// Mixin to generate color classes based on a dictionary
// Parameters are:
// * $class-name: the name of the component class to generate
// * $dictionary-values: list of the dictionary values to generate
// * $config: map of the properties to generate, their value is the suffix of the token variable
// * $generate-data-attribute: whether to generate data attribute classes
// See Button component for real usage
@mixin generate-colors($class-name, $dictionary-values, $config, $generate-data-attribute: false) {
    $component-infix: spirit-string.convert-pascal-case-to-kebab-case(
        spirit-string.remove-prefix($class-name, 'UNSTABLE_')
    );

    @each $dictionary-group-name, $dictionary-group-values in $dictionary-values {
        @each $dictionary-item-name, $dictionary-item-value in $dictionary-group-values {
            $data-attribute-selector: if(
                $generate-data-attribute,
                '.#{$class-name}[data-spirit-color="#{$dictionary-item-name}"]',
                null
            );

            .#{$class-name}--#{$dictionary-item-name},
            #{$data-attribute-selector} {
                @each $property-name, $property-value in $config {
                    $color-group: if(
                        $dictionary-group-name == $dictionary-item-name,
                        $dictionary-group-name,
                        #{$dictionary-group-name}-#{$dictionary-item-name}
                    );

                    --#{tokens.$css-variable-prefix}#{$component-infix}-#{$property-name}: var(
                        --#{tokens.$css-variable-prefix}color-#{$color-group}-#{$property-value}
                    );
                }
            }
        }
    }
}

// Mixin to reset button styling for individual link variants.
// Parameters are:
// * $dictionary-values: list of the dictionary values to generate
@mixin prepare-button-links($dictionary-values) {
    $selectors: ();

    @each $dictionary-value in $dictionary-values {
        $selectors: list.append($selectors, 'button.link-#{$dictionary-value}');
    }

    #{spirit-list.to-string($selectors, ', ')} {
        @include reset.button();
        @include links.base();

        user-select: text;
    }
}

// Mixin to generate link color classes based on a dictionary
// Parameters are:
// * $selector: the selector to generate
// * $dictionary-values: list of the dictionary values to generate
// * $tokens: map of the tokens to generate
// * $print-values: list of the print values to generate
@mixin generate-link-colors($selector, $dictionary-values, $states: (default, hover, active)) {
    @each $dictionary-value in $dictionary-values {
        @each $state in $states {
            $variant-class: if($state == 'default', '#{$dictionary-value}', '#{$dictionary-value}:#{$state}');

            #{$selector}-#{string.unquote($variant-class)} {
                color: var(
                    --#{tokens.$css-variable-prefix}color-link-#{string.unquote(
                            $dictionary-value
                        )}-state-#{string.unquote($state)}
                );
            }
        }
    }
}

// Mixin to generate placement classes based on a dictionary
// Parameters are:
// * $class-name: the name of the component class to generate
// * $dictionary-values: map of the placements to generate
// * $offset: offset of child from its parent, typically for an arrow
// * $has-arrow: whether the component has an arrow
@mixin generate-placements($class-name, $dictionary-values, $offset: 0, $is-controlled: false, $has-arrow: false) {
    $prefix: spirit-string.convert-pascal-case-to-kebab-case($class-name);

    @each $placement in $dictionary-values {
        .#{$class-name}[data-spirit-placement='#{$placement}'] {
            @include placement.child-variant($prefix, $placement, $offset, $is-controlled);
        }

        @if $has-arrow {
            .#{$class-name}[data-spirit-placement='#{$placement}'] > .#{$class-name}__arrow {
                @include placement.arrow-variant(
                    $prefix,
                    placement.transform($placement, $main-axis-inverse: true),
                    $is-controlled
                );
            }
        }
    }
}

// Mixin to generate size classes based on a config
// Parameters are:
// * $class-name: the name of the component class to generate
// * $sizes: map of the size variables to generate
@mixin generate-sizes($class-name, $sizes) {
    @each $size, $variables in $sizes {
        .#{$class-name}--#{$size} {
            $component-infix: spirit-string.convert-pascal-case-to-kebab-case(
                spirit-string.remove-prefix($class-name, 'UNSTABLE_')
            );

            @each $variable-key, $variable-value in $variables {
                @if $variable-key == 'typography' {
                    @include typography.generate($variable-value);
                } @else {
                    --#{tokens.$css-variable-prefix}#{$component-infix}-#{$variable-key}: #{$variable-value};
                }
            }
        }
    }
}
