@use '@justeattakeaway/pie-css/scss' as p;

@mixin switch-transition($property) {
    @media (prefers-reduced-motion: no-preference) {
        transition: $property 0.15s cubic-bezier(0.4, 0, 0.9, 1) 0s;
    }
}

:host {
    display: block;
}

*,
*:before,
*:after {
    cursor: inherit;
}

.c-switch-wrapper {
    display: inline-flex;
    align-items: center;
    gap: var(--dt-spacing-b);
    vertical-align: top; // This prevents the extra space at the bottom when the label is not displayed
    font-family: var(--dt-font-body-l-family);
    cursor: pointer;

    &[disabled] {
        cursor: not-allowed;
    }
}

.c-switch {
    --int-states-mixin-bg-color: var(--dt-color-interactive-form);
    --switch-bg-color--checked: var(--dt-color-interactive-brand);
    --switch-bg-color--disabled: var(--dt-color-disabled-01);
    --switch-bg-color--checked-disabled: var(--dt-color-support-brand-tonal);
    --switch-width: 48px;
    --switch-height: 24px;
    --switch-control-size: 20px;
    --switch-padding: 2px;
    --switch-radius: var(--dt-radius-rounded-e);
    --switch-translation: calc(var(--switch-width) - var(--switch-control-size) - 2 * var(--switch-padding));

    position: relative;
    display: flex;
    width: var(--switch-width);
    height: var(--switch-height);
    flex-shrink: 0;
    padding: var(--switch-padding);
    border-radius: var(--switch-radius);
    background-color: var(--int-states-mixin-bg-color);

    @include p.interactive-states('--dt-color-interactive-form');

    &[checked] {
        --int-states-mixin-bg-color: var(--dt-color-interactive-brand);

        @include p.interactive-states('--dt-color-interactive-brand');
    }

    [disabled] & {
        --int-states-mixin-bg-color: var(--switch-bg-color--disabled);

        pointer-events: none;
    }

    [disabled] &[checked] {
        --int-states-mixin-bg-color: var(--switch-bg-color--checked-disabled);
    }

    &:has(.c-switch-input:focus-visible) {
        @include p.focus;
    }
}

// Inside an interactive container (such as a `pie-list-item`) the whole container is the click
// target, so the track should tint with the container rather than only on a direct hover of the
// switch. The container exposes its current hover/active tint as `--interactive-container-tint` (an
// inherited custom property that flows through the slot into this shadow tree); we layer it over
// the track. We also opt the switch out of its own hover/active tint here, so hovering the switch
// directly (which also hovers the container) does not tint twice. The class is added by the
// component when it consumes an ancestor's ARIA context.
.c-switch--in-interactive-container {
    background-image: linear-gradient(var(--interactive-container-tint, transparent) 0 0);

    &:hover:not(:disabled),
    &:active:not(:disabled) {
        --int-states-mixin-bg-color: var(--dt-color-interactive-form);
    }

    &[checked]:hover:not(:disabled),
    &[checked]:active:not(:disabled) {
        --int-states-mixin-bg-color: var(--dt-color-interactive-brand);
    }
}

.c-switch-input {
    @include p.visually-hidden;

    &:disabled {
        background-color: transparent;
    }
}

.c-switch-control {
    position: absolute;
    left: 2px;
    width: var(--switch-control-size);
    height: var(--switch-control-size);
    border-radius: var(--switch-radius);
    background-color: var(--dt-color-interactive-light);
    padding: var(--switch-padding);

    .c-switch-wrapper:dir(rtl) & {
        position: absolute;
        left: initial;
        right: 2px;
    }

    .c-pieIcon--check {
        vertical-align: top;
    }

    .c-switch[checked] & {
        transform: translateX(var(--switch-translation));

        .c-pieIcon--check {
            color: var(--dt-color-interactive-brand);
        }
    }

    .c-switch-input:disabled ~ & {
        color: var(--switch-bg-color--disabled);

        .c-pieIcon--check {
            color: var(--switch-bg-color--disabled);
        }
    }
}

.c-switch-label {
    color: var(--dt-color-content-default-solid);
}

// The description is only required for screen readers so we need to visually hide the description
.c-switch-description {
    @include p.visually-hidden;
}

.c-switch-wrapper--label-leading {
    flex-direction: row-reverse;
}

.c-switch-wrapper--label-trailing {
    flex-direction: row;
}

.c-switch-wrapper--allow-animation {
    /* stylelint-disable-next-line no-descending-specificity */
    .c-switch {
        @include switch-transition(background-color);

        &[checked] {
            @include switch-transition(background-color);
        }
    }

    /* stylelint-disable-next-line no-descending-specificity */
    .c-switch-control {
        @include switch-transition(transform);

        .c-switch[checked] & {
            @include switch-transition(transform);

            .c-pieIcon--check {
                @include switch-transition(color);
            }
        }

        .c-switch-input:disabled ~ & {
            .c-pieIcon--check {
                @include switch-transition(color);
            }
        }
    }
}

.c-switch-wrapper:dir(rtl) {
    .c-switch[checked] .c-switch-control {
        transform: translateX(calc(-1 * var(--switch-translation)));
    }
}
