@use 'sass:map';
@use '../../config';
@use '../../functions' as *;
@use '../../schemas/' as *;
@use '../../../utils/map' as *;
@use '../../../color/functions' as *;
@use '../../../elevations/' as *;

////
/// @package theming
/// @group themes
/// @access public
/// @author <a href="https://github.com/simeonoff" target="_blank">Simeon Simeonoff</a>
/// @author <a href="https://github.com/desig9stein" target="_blank">Marin Popov</a>
////

/// Switch Theme
///
/// PRIMARY TOKENS:
/// - `$track-on-color` — The ON state track color.
/// - `$track-off-color` — The OFF state track color.
///
/// Derived colors are auto-calculated for contrast.
///
/// @param {Map} $schema [$light-material-schema] - The schema used as basis for styling the component.
/// @param {Color} $thumb-on-color [null] - The color of the thumb when the switch is on. Auto-derived from track-on-color (non-material) or bidirectional with track-on-color (material).
/// @param {Color} $track-on-color [null] - The color of the track when the switch is on. PRIMARY for ON state.
/// @param {Color} $track-on-hover-color [null] - The color of the track when the switch is on and hovered. Auto-derived from track-on-color.
/// @param {Color} $thumb-off-color [null] - The color of the thumb when the switch is off. Auto-derived from track-off-color or border-color.
/// @param {Color} $thumb-off-hover-color [null] - The color of the thumb when the switch is off and hovered. Auto-derived from thumb-off-color.
/// @param {Color} $track-off-color [null] - The color of the track when the switch is off. PRIMARY for OFF state.
/// @param {Color} $thumb-disabled-color [null] - The color of the thumb when the switch is disabled. Auto-derived from thumb-off-color.
/// @param {Color} $thumb-on-disabled-color [null] - The color of the thumb when the switch is on and disabled. Auto-derived from thumb-on-color.
/// @param {Color} $track-disabled-color [null] - The color of the track when the switch is disabled. Auto-derived from track-off-color.
/// @param {Color} $track-on-disabled-color [null] - The color of the track when the switch is on and disabled. Auto-derived from track-on-color.
/// @param {Color} $label-color [null] - The color of the switch label
/// @param {Color} $label-hover-color [null] - The color of the switch label on hover.
/// @param {Color} $label-disabled-color [null] - The color of the switch label when the switch is disabled
/// @param {List} $resting-shadow [null] - The shadow used for the thumb in resting state of the switch.
/// @param {List} $hover-shadow [null] - The shadow used for the thumb in hover state of the switch.
/// @param {List} $disabled-shadow [null] - The shadow used for the thumb in disable state of the switch.
/// @param {List} $border-radius-track [null] - The border radius used for switch track.
/// @param {List} $border-radius-thumb [null] - The border radius used for switch thumb.
/// @param {List} $border-radius-ripple [null] - The border radius used for switch ripple.
/// @param {Color} $border-color [null] - The border color of the switch. Auto-derived from thumb-off-color.
/// @param {Color} $border-hover-color [null] - The border color of the switch on hover. Auto-derived from track-off-color or border-color.
/// @param {Color} $border-disabled-color [null] - The border color of the switch when it is disabled. Auto-derived from border-color.
/// @param {Color} $border-on-color [null] - The border color when the switch is on. Auto-derived from track-on-color.
/// @param {Color} $border-on-hover-color [null] - The border color when the switch is on and hovered. Auto-derived from border-on-color.
/// @param {Color} $focus-outline-color [null] - The focus outlined color. Auto-derived from border-color (indigo) or track-on-color (bootstrap).
/// @param {Color} $focus-outline-color-focused [null] - The focus outlined color for focused state. Auto-derived from border-on-color (indigo).
/// @param {Color} $focus-fill-color [null] - The focus fill color. Auto-derived from track-on-color (bootstrap).
/// @param {Color} $focus-fill-hover-color [null] - The focus fill color on hover. Auto-derived from focus-fill-color.
/// @requires $light-material-schema
///
/// @example scss - Set custom track and thumb on colors
///   $my-switch-theme: switch-theme($thumb-on-color: black, $track-on-color: yellow);
///   // Pass the theme to the css-vars() mixin
///   @include css-vars($my-switch-theme);
@function switch-theme(
    $schema: $light-material-schema,

    $thumb-on-color: null,
    $track-on-color: null,
    $track-on-hover-color: null,

    $thumb-off-color: null,
    $thumb-off-hover-color: null,
    $track-off-color: null,

    $track-disabled-color: null,
    $track-on-disabled-color: null,
    $thumb-disabled-color: null,
    $thumb-on-disabled-color: null,

    $label-color: null,
    $label-hover-color: null,
    $label-disabled-color: null,

    $resting-shadow: null,
    $hover-shadow: null,
    $disabled-shadow: null,

    $border-radius-track: null,
    $border-radius-thumb: null,
    $border-radius-ripple: null,
    $border-color: null,
    $border-hover-color: null,
    $border-disabled-color: null,
    $border-on-color: null,
    $border-on-hover-color: null,
    $focus-outline-color: null,
    $focus-outline-color-focused: null,
    $focus-fill-color: null,
    $focus-fill-hover-color: null
) {
    $selector: #{config.element-prefix() + '-' + 'switch'};
    $switch-schema: ();

    @if map.has-key($schema, 'switch') {
        $switch-schema: map.get($schema, 'switch');
    } @else {
        $switch-schema: $schema;
    }

    $theme: digest-schema($switch-schema);
    $variant: map.get($theme, '_meta', 'theme');

    @if $variant == 'material' {
        @if not($track-off-color) and $thumb-off-color {
            $track-off-color: dynamic-shade(var(--thumb-off-color), $offset: 20);
        }

        @if not($thumb-off-color) and $track-off-color {
            $thumb-off-color: dynamic-shade(var(--track-off-color), $offset: 20);
        }

        @if not($thumb-off-hover-color) and $thumb-off-color {
            $thumb-off-hover-color: var(--thumb-off-color);
        }

        @if not($thumb-disabled-color) and $thumb-off-color {
            $thumb-disabled-color: hsl(from var(--thumb-off-color) h s calc(l + 20));
        }

        @if not($track-on-color) and $thumb-on-color {
            $track-on-color: dynamic-shade(var(--thumb-on-color), $offset: 20);
        }

        @if not($thumb-on-color) and $track-on-color {
            $thumb-on-color: dynamic-shade(var(--track-on-color), $offset: 20);
        }

        @if not($track-on-hover-color) and $track-on-color {
            $track-on-hover-color: var(--track-on-color);
        }

        @if not($thumb-on-disabled-color) and $thumb-on-color {
            $thumb-on-disabled-color: hsl(from var(--thumb-on-color) h s calc(l + 20));
        }
    } @else {
        @if not($thumb-off-color) and $track-off-color {
            $thumb-off-color: hsl(from adaptive-contrast(var(--track-off-color)) h s l / 0.8);
        }

        @if not($border-color) and $thumb-off-color {
            $border-color: var(--thumb-off-color);
        }

        @if not($thumb-off-color) and $border-color {
            $thumb-off-color: var(--border-color);
        }

        @if not($border-hover-color) and $track-off-color {
            $border-hover-color: dynamic-shade(var(--track-off-color));
        }

        @if not($border-hover-color) and $border-color {
            $border-hover-color: dynamic-shade(var(--border-color));
        }

        @if not($thumb-off-hover-color) and $thumb-off-color {
            $thumb-off-hover-color: dynamic-shade(var(--thumb-off-color));
        }

        @if not($thumb-on-color) and $track-on-color {
            $thumb-on-color: adaptive-contrast(var(--track-on-color));
        }

        @if not($track-on-hover-color) and $track-on-color {
            $track-on-hover-color: dynamic-shade(var(--track-on-color));
        }

        @if not($border-on-color) and $track-on-color {
            $border-on-color: var(--track-on-color);
        }

        @if not($border-on-hover-color) and $border-on-color {
            $border-on-hover-color: dynamic-shade(var(--border-on-color));
        }

        @if not($thumb-disabled-color) and $thumb-off-color {
            $thumb-disabled-color: hsl(from var(--thumb-off-color) h s l / 0.3);
        }

        @if not($border-disabled-color) and $border-color {
            $border-disabled-color: hsl(from var(--border-color) h s l / 0.3);
        }

        @if not($thumb-on-disabled-color) and $thumb-on-color {
            $thumb-on-disabled-color: hsl(from var(--thumb-on-color) h s l / 0.3);
        }

        @if $variant == 'bootstrap' {
            @if not($focus-fill-color) and $track-on-color {
                $focus-fill-color: dynamic-shade(var(--track-on-color), $offset: 8);
            }

            @if not($focus-outline-color) and $focus-fill-color {
                $focus-outline-color: hsl(from var(--focus-fill-color) h s l / 0.5);
            }

            @if not($focus-fill-hover-color) and $focus-fill-color {
                $focus-fill-hover-color: dynamic-shade(var(--focus-fill-color));
            }
        }

        @if $variant == 'indigo' {
            @if not($focus-outline-color) and $border-color {
                $focus-outline-color: hsl(from var(--border-color) h s l / 0.5);
            }

            @if not($focus-outline-color-focused) and $border-on-color {
                $focus-outline-color-focused: hsl(from var(--border-on-color) h s l / 0.5);
            }
        }
    }

    @if not($track-disabled-color) and $track-off-color {
        $track-disabled-color: hsl(from var(--track-off-color) h s l / 0.5);
    }

    @if not($track-on-disabled-color) and $track-on-color {
        $track-on-disabled-color: hsl(from var(--track-on-color) h s l / 0.5);
    }

    @if not($resting-shadow) {
        $resting-elevation: map.get($switch-schema, 'resting-elevation');
        $resting-shadow: elevation($resting-elevation);
    }

    @if not($hover-shadow) {
        $hover-elevation: map.get($switch-schema, 'hover-elevation');
        $hover-shadow: elevation($hover-elevation);
    }

    @if not($disabled-shadow) {
        $disabled-elevation: map.get($switch-schema, 'disabled-elevation');
        $disabled-shadow: elevation($disabled-elevation);
    }

    @if not($border-radius-track) {
        $border-radius-track: map.get($theme, 'border-radius-track');
    }

    @if not($border-radius-thumb) {
        $border-radius-thumb: map.get($theme, 'border-radius-thumb');
    }

    @if not($border-radius-ripple) {
        $border-radius-ripple: map.get($theme, 'border-radius-ripple');
    }

    @return extend(
        $theme,
        (
            selector: $selector,

            thumb-on-color: $thumb-on-color,
            track-on-color: $track-on-color,
            track-on-hover-color: $track-on-hover-color,

            thumb-off-color: $thumb-off-color,
            thumb-off-hover-color: $thumb-off-hover-color,
            track-off-color: $track-off-color,

            track-disabled-color: $track-disabled-color,
            track-on-disabled-color: $track-on-disabled-color,
            thumb-disabled-color: $thumb-disabled-color,
            thumb-on-disabled-color: $thumb-on-disabled-color,

            label-color: $label-color,
            label-hover-color: $label-hover-color,
            label-disabled-color: $label-disabled-color,

            resting-elevation: $resting-shadow,
            hover-elevation: $hover-shadow,
            disabled-elevation: $disabled-shadow,

            border-radius-track: $border-radius-track,
            border-radius-thumb: $border-radius-thumb,
            border-radius-ripple: $border-radius-ripple,
            border-color: $border-color,
            border-hover-color: $border-hover-color,
            border-disabled-color: $border-disabled-color,
            border-on-color: $border-on-color,
            border-on-hover-color: $border-on-hover-color,
            focus-outline-color: $focus-outline-color,
            focus-outline-color-focused: $focus-outline-color-focused,
            focus-fill-color: $focus-fill-color,
            focus-fill-hover-color: $focus-fill-hover-color,
        )
    );
}
