@use 'sass:list';
@use 'sass:meta';
@use 'sass:string';
@use '../schemas' as *;
@use '../../base' as *;
@use '../../components' as *;
@use 'igniteui-theming/sass/color' as *;
@use 'igniteui-theming/sass/elevations' as *;
@use 'igniteui-theming/sass/elevations/presets' as elevations;
@use 'igniteui-theming/sass/utils' as *;
@use 'igniteui-theming/sass/themes' as *;
@use 'igniteui-theming/sass/themes/charts' as *;

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

/// Default noop handler for theme map transforms
/// @access private
@function theme-noop($arg) { @return $arg; }

/// Generates an Ignite UI for Angular global theme.
/// @param {Map} $palette - An palette to be used by the global theme.
/// @param {Map} $schema [$light-material-schema] - The schema used as basis for styling the components.
/// @param {List} $exclude [( )] - A list of igx components to be excluded from the global theme styles.
/// @param {Number} $roundness [null] - Sets the global roundness factor (the value can be any decimal fraction between 0 and 1) for all components.
/// @param {Boolean} $elevation [true] - Turns on/off elevations for all components in the theme.
/// @param {Map} $elevations [$elevations] - The elevation map to be used by all component themes.
/// @requires $light-material-schema
/// @requires {function} is-component
/// @requires {function} is-used
@mixin theme(
    $palette,
    $schema: $light-material-schema,
    $exclude: (),
    $roundness: null,
    $elevation: true,
    $elevations: elevations.$material-elevations,
) {
    @include theme-internal(
        $palette: $palette,
        $schema: $schema,
        $exclude: $exclude,
        $roundness: $roundness,
        $elevation: $elevation,
        $elevations: $elevations
    )
}

/// Generates an Ignite UI for Angular global theme.
/// @access private
/// @param {Map} $palette - An palette to be used by the global theme.
/// @param {Map} $schema [$light-schema] - The schema used as basis for styling the components.
/// @param {List} $exclude [( )] - A list of igx components to be excluded from the global theme styles.
/// @param {Number} $roundness [null] - Sets the global roundness factor (the value can be any decimal fraction between 0 and 1) for all components.
/// @param {Boolean} $elevation [true] - Turns on/off elevations for all components in the theme.
/// @param {Map} $elevations [$elevations] - The elevation map to be used by all component themes.
/// @requires $light-material-schema
/// @requires {function} is-component
/// @requires {function} is-used
@mixin theme-internal(
    $palette,
    $schema: $light-material-schema,
    $exclude: (),
    $roundness: null,
    $elevation: true,
    $elevations: elevations.$material-elevations,
    $theme-handler: meta.get-function('theme-noop'),
) {
    // Stores all excluded component styles
    $excluded: ();
    $scope: if(is-root(), ':root', '&');

    #{$scope} {
        --ig-size-small: 1;
        --ig-size-medium: 2;
        --ig-size-large: 3;

        --ig-spacing-small: 1;
        --ig-spacing-medium: 1;
        --ig-spacing-large: 1;

        --ig-spacing-inline-small: 1;
        --ig-spacing-inline-medium: 1;
        --ig-spacing-inline-large: 1;

        --ig-spacing-block-small: 1;
        --ig-spacing-block-medium: 1;
        --ig-spacing-block-large: 1;
    }

    @if not(list.index($exclude, 'palette')) {
        @include palette($palette);
    }

    @if not(list.index($exclude, 'elevations')) {
        @include elevations($elevations);
    }

    @if $elevation == false {
        #{$scope} {
            --ig-elevation-factor: 0;
        }
    }

    @if $roundness {
        #{$scope} {
            --ig-radius-factor: #{$roundness};
        }
    }

    @if list.length($exclude) > 0 {
        $excluded: is-component($exclude);
    }

    @if is-used('igx-ripple', $exclude) {
        $ripple-theme-map: ripple-theme(
            $schema: $schema,
        );
        $ripple-theme-map: meta.call($theme-handler, $ripple-theme-map);
        @include ripple($ripple-theme-map);
    }

    @if is-used('igx-avatar', $exclude) {
        $avatar-theme-map: avatar-theme(
            $schema: $schema,
        );
        $avatar-theme-map: meta.call($theme-handler, $avatar-theme-map);
        @include avatar($avatar-theme-map);
    }

    @if is-used('igx-action-strip', $exclude) {
        $action-strip-theme-map: action-strip-theme(
            $schema: $schema,
        );
        $action-strip-theme-map: meta.call($theme-handler, $action-strip-theme-map);
        @include action-strip($action-strip-theme-map);
    }

    @if is-used('igx-badge', $exclude) {
        $badge-theme-map: badge-theme(
            $schema: $schema,
        );
        $badge-theme-map: meta.call($theme-handler, $badge-theme-map);
        @include badge($badge-theme-map);
    }

    @if is-used('igx-bottom-nav', $exclude) {
        $bottom-nav-theme-map: bottom-nav-theme(
            $schema: $schema,
        );
        $bottom-nav-theme-map: meta.call($theme-handler, $bottom-nav-theme-map);
        @include bottom-nav($bottom-nav-theme-map);
    }

    @if is-used('igx-button', $exclude) {
        $button-theme-map: button-theme(
            $schema: $schema,
        );
        $button-theme-map: meta.call($theme-handler, $button-theme-map);
        @include button($button-theme-map);
    }

    @if is-used('igx-button-group', $exclude) {
        $button-group-theme-map: button-group-theme(
            $schema: $schema,
        );
        $button-group-theme-map: meta.call($theme-handler, $button-group-theme-map);
        @include button-group($button-group-theme-map);
    }

    @if is-used('igx-banner', $exclude) {
        $banner-theme-map: banner-theme(
            $schema: $schema,
        );
        $banner-theme-map: meta.call($theme-handler, $banner-theme-map);
        @include banner($banner-theme-map);
    }

    @if is-used('igx-calendar', $exclude) {
        $calendar-theme-map: calendar-theme(
            $schema: $schema,
        );
        $calendar-theme-map: meta.call($theme-handler, $calendar-theme-map);
        @include calendar($calendar-theme-map);
    }

    @if is-used('igx-card', $exclude) {
        $card-theme-map: card-theme(
            $schema: $schema,
        );
        $card-theme-map: meta.call($theme-handler, $card-theme-map);
        @include card($card-theme-map);
    }

    @if is-used('igx-carousel', $exclude) {
        $carousel-theme-map: carousel-theme(
            $schema: $schema,
        );
        $carousel-theme-map: meta.call($theme-handler, $carousel-theme-map);
        @include carousel($carousel-theme-map);
    }

    @if is-used('igx-splitter', $exclude) {
        $splitter-theme-map: splitter-theme(
            $schema: $schema,
        );
        $splitter-theme-map: meta.call($theme-handler, $splitter-theme-map);
        @include splitter($splitter-theme-map);
    }

    @if is-used('data-chart', $exclude) {
        $data-chart-theme-map: data-chart-theme(
            $schema: $schema,
        );
        $data-chart-theme-map: meta.call($theme-handler, $data-chart-theme-map);
        @include  css-vars($data-chart-theme-map);
    }

    @if is-used('doughnut-chart', $exclude) {
        $doughnut-chart-theme-map: doughnut-chart-theme(
            $schema: $schema,
        );
        $doughnut-chart-theme-map: meta.call($theme-handler, $doughnut-chart-theme-map);
        @include  css-vars($doughnut-chart-theme-map);
    }

    @if is-used('linear-gauge', $exclude) {
        $linear-gauge-theme-map: linear-gauge-theme(
            $schema: $schema,
        );
        $linear-gauge-theme-map: meta.call($theme-handler, $linear-gauge-theme-map);
        @include  css-vars($linear-gauge-theme-map);
    }

    @if is-used('radial-gauge', $exclude) {
        $radial-gauge-theme-map: radial-gauge-theme(
            $schema: $schema,
        );
        $radial-gauge-theme-map: meta.call($theme-handler, $radial-gauge-theme-map);
        @include  css-vars($radial-gauge-theme-map);
    }

    @if is-used('financial-chart', $exclude) {
        $financial-chart-theme-map: financial-chart-theme(
            $schema: $schema,
        );
        $financial-chart-theme-map: meta.call($theme-handler, $financial-chart-theme-map);
        @include  css-vars($financial-chart-theme-map);
    }

    @if is-used('bullet-graph', $exclude) {
        $bullet-graph-theme-map: bullet-graph-theme(
            $schema: $schema,
        );
        $bullet-graph-theme-map: meta.call($theme-handler, $bullet-graph-theme-map);
        @include  css-vars($bullet-graph-theme-map);
    }

    @if is-used('category-chart', $exclude) {
        $category-chart-theme-map: category-chart-theme(
            $schema: $schema,
        );
        $category-chart-theme-map: meta.call($theme-handler, $category-chart-theme-map);
        @include  css-vars($category-chart-theme-map);
    }

    @if is-used('geo-map', $exclude) {
        $geo-map-theme-map: geo-map-theme(
            $schema: $schema,
        );
        $geo-map-theme-map: meta.call($theme-handler, $geo-map-theme-map);
        @include  css-vars($geo-map-theme-map);
    }

    @if is-used('pie-chart', $exclude) {
        $pie-chart-theme-map: pie-chart-theme(
            $schema: $schema,
        );
        $pie-chart-theme-map: meta.call($theme-handler, $pie-chart-theme-map);
        @include  css-vars($pie-chart-theme-map);
    }

    @if is-used('sparkline', $exclude) {
        $sparkline-theme-map: sparkline-theme(
            $schema: $schema,
        );
        $sparkline-theme-map: meta.call($theme-handler, $sparkline-theme-map);
        @include  css-vars($sparkline-theme-map);
    }

    @if is-used('funnel-chart', $exclude) {
        $funnel-chart-theme-map: funnel-chart-theme(
            $schema: $schema,
        );
        $funnel-chart-theme-map: meta.call($theme-handler, $funnel-chart-theme-map);
        @include  css-vars($funnel-chart-theme-map);
    }

    @if is-used('shape-chart', $exclude) {
        $shape-chart-theme-map: shape-chart-theme(
            $schema: $schema,
        );
        $shape-chart-theme-map: meta.call($theme-handler, $shape-chart-theme-map);
        @include  css-vars($shape-chart-theme-map);
    }

    @if is-used('igx-checkbox', $exclude) {
        $checkbox-theme-map: checkbox-theme(
            $schema: $schema,
        );
        $checkbox-theme-map: meta.call($theme-handler, $checkbox-theme-map);
        @include checkbox($checkbox-theme-map);
    }

    @if is-used('igx-chip', $exclude) {
        $chip-theme-map: chip-theme(
            $schema: $schema,
        );
        $chip-theme-map: meta.call($theme-handler, $chip-theme-map);
        @include chip($chip-theme-map);
    }

    @if is-used('igx-column-actions', $exclude) {
        $column-actions-theme-map: column-actions-theme(
            $schema: $schema,
        );
        $column-actions-theme-map: meta.call($theme-handler, $column-actions-theme-map);
        @include column-actions($column-actions-theme-map);
    }

    @if is-used('igx-combo', $exclude) {
        $combo-theme-map: combo-theme(
            $schema: $schema,
        );
        $combo-theme-map: meta.call($theme-handler, $combo-theme-map);
        @include combo($combo-theme-map);
    }

    @if is-used('igx-select', $exclude) {
        $select-theme-map: select-theme(
            $schema: $schema,
        );
        $select-theme-map: meta.call($theme-handler, $select-theme-map);
        @include select($select-theme-map);
    }

    @if is-used('igx-date-picker', $exclude) {
        $calendar-theme-map: calendar-theme(
            $schema: $schema,
        );
        $calendar-theme-map: meta.call($theme-handler, $calendar-theme-map);
        @include date-picker($calendar-theme-map);
    }

    @if is-used('igx-date-range-picker', $exclude) {
        $date-range-picker-theme-map: date-range-picker-theme(
            $schema: $schema,
        );
        $date-range-picker-theme-map: meta.call($theme-handler, $date-range-picker-theme-map);
        @include date-range-picker($date-range-picker-theme-map);
    }

    @if is-used('igx-dialog', $exclude) {
        $dialog-theme-map: dialog-theme(
            $schema: $schema,
        );
        $dialog-theme-map: meta.call($theme-handler, $dialog-theme-map);
        @include dialog($dialog-theme-map);
    }

    @if is-used('igx-divider', $exclude) {
        $divider-theme-map: divider-theme(
            $schema: $schema,
        );
        $divider-theme-map: meta.call($theme-handler, $divider-theme-map);
        @include divider($divider-theme-map);
    }

    @if is-used('igc-dockmanager', $exclude) {
        $dock-manager-theme-map: dock-manager-theme(
            $schema: $schema,
        );
        $dock-manager-theme-map: meta.call($theme-handler, $dock-manager-theme-map);
        @include dock-manager($dock-manager-theme-map);
    }

    @if is-used('igc-rating', $exclude) {
        $rating-theme-map: rating-theme(
            $schema: $schema,
        );
        $rating-theme-map: meta.call($theme-handler, $rating-theme-map);
        @include rating($rating-theme-map);
    }

    @if is-used('igx-drop-down', $exclude) {
        $drop-down-theme-map: drop-down-theme(
            $schema: $schema,
        );
        $drop-down-theme-map: meta.call($theme-handler, $drop-down-theme-map);
        @include drop-down($drop-down-theme-map);
    }

    @if is-used('igx-expansion-panel', $exclude) {
        $expansion-panel-theme-map: expansion-panel-theme(
            $schema: $schema,
        );
        $expansion-panel-theme-map: meta.call($theme-handler, $expansion-panel-theme-map);
        @include expansion-panel($expansion-panel-theme-map);
    }

    @if is-used('igx-grid', $exclude) {
        $grid-theme-map: grid-theme(
            $schema: $schema,
        );
        $grid-theme-map: meta.call($theme-handler, $grid-theme-map);
        @include grid($grid-theme-map);
    }

    @if is-used('igx-grid-summary', $exclude) {
        $grid-summary-theme-map: grid-summary-theme(
            $schema: $schema,
        );
        $grid-summary-theme-map: meta.call($theme-handler, $grid-summary-theme-map);
        @include grid-summary($grid-summary-theme-map);
    }

    @if is-used('igx-grid-toolbar', $exclude) {
        $grid-toolbar-theme-map: grid-toolbar-theme(
            $schema: $schema,
        );
        $grid-toolbar-theme-map: meta.call($theme-handler, $grid-toolbar-theme-map);
        @include grid-toolbar($grid-toolbar-theme-map);
    }

    @if is-used('igx-pivot-data-selector', $exclude) {
        $pivot-data-selector-theme-map: pivot-data-selector-theme(
            $schema: $schema,
        );
        $pivot-data-selector-theme-map: meta.call($theme-handler, $pivot-data-selector-theme-map);
        @include pivot-data-selector($pivot-data-selector-theme-map);
    }

    @if is-used('igx-highlight', $exclude) {
        $highlight-theme-map: highlight-theme(
            $schema: $schema,
        );
        $highlight-theme-map: meta.call($theme-handler, $highlight-theme-map);
        @include highlight($highlight-theme-map);
    }

    @if is-used('igx-icon', $exclude) {
        $icon-theme-map: icon-theme(
            $schema: $schema,
        );
        $icon-theme-map: meta.call($theme-handler, $icon-theme-map);
        @include icon($icon-theme-map);
    }

    @if is-used('igx-input-group', $exclude) {
        $input-group-theme-map: input-group-theme(
            $schema: $schema,
        );
        $input-group-theme-map: meta.call($theme-handler, $input-group-theme-map);
        @include input-group($input-group-theme-map);
    }

    @if is-used('igx-list', $exclude) {
        $list-theme-map: list-theme(
            $schema: $schema,
        );
        $list-theme-map: meta.call($theme-handler, $list-theme-map);
        @include list($list-theme-map);
    }

    @if is-used('igx-navbar', $exclude) {
        $navbar-theme-map: navbar-theme(
            $schema: $schema,
        );
        $navbar-theme-map: meta.call($theme-handler, $navbar-theme-map);
        @include navbar($navbar-theme-map);
    }

    @if is-used('igx-nav-drawer', $exclude) {
        $navdrawer-theme-map: navdrawer-theme(
            $schema: $schema,
        );
        $navdrawer-theme-map: meta.call($theme-handler, $navdrawer-theme-map);
        @include navdrawer($navdrawer-theme-map);
    }

    @if is-used('igx-overlay', $exclude) {
        $overlay-theme-map: overlay-theme(
            $schema: $schema,
        );
        $overlay-theme-map: meta.call($theme-handler, $overlay-theme-map);
        @include overlay($overlay-theme-map);
    }

    @if is-used('igx-paginator', $exclude) {
        $paginator-theme-map: paginator-theme(
            $schema: $schema,
        );
        $paginator-theme-map: meta.call($theme-handler, $paginator-theme-map);
        @include paginator($paginator-theme-map);
    }

    @if is-used('igx-circular-bar', $exclude) {
        $progress-circular-theme-map: progress-circular-theme(
            $schema: $schema,
        );
        $progress-circular-theme-map: meta.call($theme-handler, $progress-circular-theme-map);
        @include progress-circular($progress-circular-theme-map);
    }

    @if is-used('igx-linear-bar', $exclude) {
        $progress-linear-theme-map: progress-linear-theme(
            $schema: $schema,
        );
        $progress-linear-theme-map: meta.call($theme-handler, $progress-linear-theme-map);
        @include progress-linear($progress-linear-theme-map);
    }

    @if is-used('igx-radio', $exclude) {
        $radio-theme-map: radio-theme(
            $schema: $schema,
        );
        $radio-theme-map: meta.call($theme-handler, $radio-theme-map);
        @include radio($radio-theme-map);
    }

    @if is-used('igx-query-builder', $exclude) {
        $query-builder-theme-map: query-builder-theme(
            $schema: $schema,
        );
        $query-builder-theme-map: meta.call($theme-handler, $query-builder-theme-map);
        @include query-builder($query-builder-theme-map);
    }

    @if is-used('ig-scrollbar', $exclude) {
        $scrollbar-theme-map: scrollbar-theme(
            $schema: $schema,
        );
        $scrollbar-theme-map: meta.call($theme-handler, $scrollbar-theme-map);
        @include scrollbar($scrollbar-theme-map);
    }

    @if is-used('igx-slider', $exclude) {
        $slider-theme-map: slider-theme(
            $schema: $schema,
        );
        $slider-theme-map: meta.call($theme-handler, $slider-theme-map);
        @include slider($slider-theme-map);
    }

    @if is-used('igx-snackbar', $exclude) {
        $snackbar-theme-map: snackbar-theme(
            $schema: $schema,
        );
        $snackbar-theme-map: meta.call($theme-handler, $snackbar-theme-map);
        @include snackbar($snackbar-theme-map);
    }

    @if is-used('igx-switch', $exclude) {
        $switch-theme-map: switch-theme(
            $schema: $schema,
        );
        $switch-theme-map: meta.call($theme-handler, $switch-theme-map);
        @include switch($switch-theme-map);
    }

    @if is-used('igx-tabs', $exclude) {
        $tabs-theme-map: tabs-theme(
            $schema: $schema,
        );
        $tabs-theme-map: meta.call($theme-handler, $tabs-theme-map);
        @include tabs($tabs-theme-map);
    }

    @if is-used('igx-stepper', $exclude) {
        $stepper-theme-map: stepper-theme(
            $schema: $schema,
        );
        $stepper-theme-map: meta.call($theme-handler, $stepper-theme-map);
        @include stepper($stepper-theme-map);
    }

    @if is-used('igx-toast', $exclude) {
        $toast-theme-map: toast-theme(
            $schema: $schema,
        );
        $toast-theme-map: meta.call($theme-handler, $toast-theme-map);
        @include toast($toast-theme-map);
    }

    @if is-used('igx-tooltip', $exclude) {
        $tooltip-theme-map: tooltip-theme(
            $schema: $schema,
        );
        $tooltip-theme-map: meta.call($theme-handler, $tooltip-theme-map);
        @include tooltip($tooltip-theme-map);
    }

    @if is-used('igx-time-picker', $exclude) {
        $time-picker-theme-map: time-picker-theme(
            $schema: $schema,
        );
        $time-picker-theme-map: meta.call($theme-handler, $time-picker-theme-map);
        @include time-picker($time-picker-theme-map);
    }

    @if is-used('igx-tree', $exclude) {
        $tree-theme-map: tree-theme(
            $schema: $schema,
        );
        $tree-theme-map: meta.call($theme-handler, $tree-theme-map);
        @include tree($tree-theme-map);
    }

    @if is-used('igx-watermark', $exclude) {
        $watermark-theme-map: watermark-theme(
            $schema: $schema,
        );
        $watermark-theme-map: meta.call($theme-handler, $watermark-theme-map);
        @include watermark($watermark-theme-map);
    }

    @if list.length($dropped-themes) > 0 {
        @warn string.unquote('You have excluded the following components from the theme: "#{$dropped-themes}".');
    }
}

/// A wrapper around the theme mixin. Creates a global material theme that can be used with light backgrounds.
/// @param {Map} $palette - An palette to be used by the global theme.
/// @param {List} $exclude [( )] - A list of ig components to be excluded from the global theme styles.
/// @see {mixin} theme
@mixin light-theme(
    $palette,
    $exclude: (),
    $roundness: null,
    $elevation: true,
) {
    $gray: color($palette, 'gray');
    $surface: color($palette, 'surface');

    $light-palette: palette(
        $primary: color($palette, 'primary'),
        $secondary: color($palette, 'secondary'),
        $info: color($palette, 'info'),
        $success: color($palette, 'success'),
        $warn: color($palette, 'warn'),
        $error: color($palette, 'error'),
        $surface: if($surface != #fff, $surface, #fff),
        $gray: if($gray != #9e9e9e, $gray, #000),
    );

    @include theme(
        $palette: $light-palette,
        $schema: $light-material-schema,
        $exclude: $exclude,
        $roundness: $roundness,
        $elevation: $elevation,
    );
}

/// A wrapper around the theme mixin. Creates a global material theme that can be used with dark backgrounds.
/// @param {Map} $palette - An palette to be used by the global theme.
/// @param {List} $exclude [( )] - A list of igx components to be excluded from the global theme styles.
/// @see {mixin} theme
@mixin dark-theme(
    $palette,
    $exclude: (),
    $roundness: null,
    $elevation: true,
) {
    $gray: color($palette, 'gray');
    $surface: color($palette, 'surface');

    $dark-palette: palette(
        $primary: color($palette, 'primary'),
        $secondary: color($palette, 'secondary'),
        $info: color($palette, 'info'),
        $success: color($palette, 'success'),
        $warn: color($palette, 'warn'),
        $error: color($palette, 'error'),
        $surface: if($surface != #fff, $surface, #222),
        $gray: if($gray != #9e9e9e, $gray, #fff),
    );

    @include theme(
        $palette: $dark-palette,
        $schema: $dark-material-schema,
        $exclude: $exclude,
        $roundness: $roundness,
        $elevation: $elevation,
    );
}
