@use 'true' as test;
@use '../placement';

@include test.describe('placement functions and mixins') {
    @include test.it('should return correct cross axis direction') {
        @include test.assert() {
            @include test.output() {
                --cross-axis-direction-left: #{placement.get-cross-axis-direction('left')};
                --cross-axis-direction-bottom: #{placement.get-cross-axis-direction('bottom')};
            }

            @include test.expect() {
                --cross-axis-direction-left: vertical;
                --cross-axis-direction-bottom: horizontal;
            }
        }
    }

    @include test.it('should return true for logical placements, false otherwise') {
        @include test.assert() {
            @include test.output() {
                --is-logical-left: #{placement.is-logical('left')};
                --is-logical-start: #{placement.is-logical('start')};
            }

            @include test.expect() {
                --is-logical-left: false;
                --is-logical-start: true;
            }
        }
    }

    @include test.it('should return correct physical placement') {
        @include test.assert() {
            @include test.output() {
                --logical-to-physical-start-horizontal: #{placement.translate-logical-to-physical('start', 'horizontal')};
                --logical-to-physical-start-vertical: #{placement.translate-logical-to-physical('start', 'vertical')};
            }

            @include test.expect() {
                --logical-to-physical-start-horizontal: left;
                --logical-to-physical-start-vertical: top;
            }
        }
    }

    @include test.it('should return transformed axis') {
        @include test.assert() {
            @include test.output() {
                --transform-axis-left: #{placement.transform-axis('left')};
                --transform-axis-left-inverse: #{placement.transform-axis('left', $inverse: true)};
                --transform-axis-left-physical: #{placement.transform-axis('left', $physical-direction: 'horizontal')};
                --transform-axis-left-physical-inverse: #{placement.transform-axis(
                        'left',
                        $inverse: true,
                        $physical-direction: 'horizontal'
                    )};
                --transform-axis-start: #{placement.transform-axis('start')};
                --transform-axis-start-inverse: #{placement.transform-axis('start', $inverse: true)};
                --transform-axis-start-physical: #{placement.transform-axis('start', $physical-direction: 'horizontal')};
                --transform-axis-start-physical-inverse: #{placement.transform-axis(
                        'start',
                        $inverse: true,
                        $physical-direction: 'horizontal'
                    )};
            }

            @include test.expect() {
                --transform-axis-left: left;
                --transform-axis-left-inverse: right;
                --transform-axis-left-physical: left;
                --transform-axis-left-physical-inverse: right;
                --transform-axis-start: start;
                --transform-axis-start-inverse: end;
                --transform-axis-start-physical: left;
                --transform-axis-start-physical-inverse: right;
            }
        }
    }

    @include test.describe('should return transformed placement') {
        @include test.it('physical only') {
            @include test.assert() {
                @include test.output() {
                    --transform-left: #{placement.transform('left')};
                    --transform-left-top: #{placement.transform('left-top')};
                    --transform-left-top-main-axis-inverse: #{placement.transform('left-top', $main-axis-inverse: true)};
                    --transform-left-top-main-axis-inverse-cross-axis-inverse: #{placement.transform(
                            'left-top',
                            $main-axis-inverse: true,
                            $cross-axis-inverse: true
                        )};
                    --transform-left-top-main-axis-inverse-cross-axis-inverse-physical: #{placement.transform(
                            'left-top',
                            $main-axis-inverse: true,
                            $cross-axis-inverse: true,
                            $cross-axis-physical: true
                        )};
                    --transform-left-top-spaces: #{placement.transform('left-top', $join-with: ' ')};
                }

                @include test.expect() {
                    --transform-left: left;
                    --transform-left-top: left-top;
                    --transform-left-top-main-axis-inverse: right-top;
                    --transform-left-top-main-axis-inverse-cross-axis-inverse: right-bottom;
                    --transform-left-top-main-axis-inverse-cross-axis-inverse-physical: right-bottom;
                    --transform-left-top-spaces: left top;
                }
            }
        }

        @include test.it('physical and logical') {
            @include test.assert() {
                @include test.output() {
                    --transform-top-start: #{placement.transform('top-start')};
                    --transform-top-start-main-axis-inverse: #{placement.transform(
                            'top-start',
                            $main-axis-inverse: true
                        )};
                    --transform-top-start-main-axis-inverse-cross-axis-inverse: #{placement.transform(
                            'top-start',
                            $main-axis-inverse: true,
                            $cross-axis-inverse: true
                        )};
                    --transform-top-start-main-axis-inverse-cross-axis-physical: #{placement.transform(
                            'top-start',
                            $main-axis-inverse: true,
                            $cross-axis-physical: true
                        )};
                    --transform-top-start-main-axis-inverse-cross-axis-inverse-physical: #{placement.transform(
                            'top-start',
                            $main-axis-inverse: true,
                            $cross-axis-inverse: true,
                            $cross-axis-physical: true
                        )};
                    --transform-top-start-spaces: #{placement.transform('top-start', $join-with: ' ')};
                }

                @include test.expect() {
                    --transform-top-start: top-start;
                    --transform-top-start-main-axis-inverse: bottom-start;
                    --transform-top-start-main-axis-inverse-cross-axis-inverse: bottom-end;
                    --transform-top-start-main-axis-inverse-cross-axis-physical: bottom-left;
                    --transform-top-start-main-axis-inverse-cross-axis-inverse-physical: bottom-right;
                    --transform-top-start-spaces: top start;
                }
            }
        }
    }

    @include test.it('should apply relative positioning to parent') {
        @include test.assert() {
            @include test.output() {
                .parent-test {
                    @include placement.parent();
                }
            }

            @include test.expect() {
                .parent-test {
                    position: relative;
                }
            }
        }
    }

    @include test.it('should apply absolute positioning to child with z-index') {
        @include test.assert() {
            @include test.output() {
                .child-test {
                    @include placement.child($z-index: 3);
                }
            }

            @include test.expect() {
                .child-test {
                    position: absolute;
                    z-index: 3;
                }
            }
        }
    }

    @include test.it('should apply controlled styles to child') {
        @include test.assert() {
            @include test.output() {
                .child-controlled-test {
                    @include placement.child-controlled('test', 10px);
                }
            }

            @include test.expect() {
                .child-controlled-test {
                    --test-offset-orthogonal: 0;
                    --test-offset: 10px;

                    inset: unset;
                    translate: unset;
                }
            }
        }
    }

    @include test.it('should apply custom styles to child variant') {
        @include test.assert() {
            @include test.output() {
                .child-variant-test {
                    @include placement.child-variant($prefix: 'test', $placement: 'top', $offset: 10px);
                }
            }

            @include test.expect() {
                .child-variant-test {
                    --test-offset: 10px;

                    inset: auto auto 100% 50%;
                    translate: var(--test-offset-orthogonal, -50%) calc(-1 * var(--test-offset, 0));
                    transform-origin: bottom;
                }
            }
        }

        @include test.assert() {
            @include test.output() {
                .child-variant-test {
                    @include placement.child-variant(
                        $prefix: 'test',
                        $placement: 'top',
                        $offset: 10px,
                        $is-controlled: true
                    );
                }
            }

            @include test.expect() {
                .child-variant-test {
                    --test-offset: 10px;
                    --test-offset-orthogonal: 0;

                    transform-origin: bottom;
                }
            }
        }
    }

    @include test.it('should apply styles to arrow') {
        @include test.assert() {
            @include test.output() {
                .arrow-test {
                    @include placement.arrow('test', '10px', '10px', '5px');
                }
            }

            @include test.expect() {
                .arrow-test {
                    --test-arrow-width: 10px;
                    --test-arrow-height: 10px;
                    --test-arrow-corner-offset: 5px;

                    position: absolute;
                    transform-origin: bottom center;
                }
            }
        }
    }

    @include test.it('should apply variant styles to arrow') {
        @include test.assert() {
            @include test.output() {
                .arrow-variant-test {
                    @include placement.arrow-variant('test', 'top');
                }
            }

            @include test.expect() {
                .arrow-variant-test {
                    inset: auto auto 100% 50%;
                    translate: -50% 0%;
                    rotate: z 0deg;
                }
            }
        }
    }
}
