////
/// @group init
///

// Here is the loading problem in a nutshell (and the reason to use a mixin for defaults):
//
//     // set a primary color as a default
//     $primary: red !default;
//
//     // derive another value from it
//     $link: $primary !default;
//
//     // now update the primary color
//     $primary: blue;
//
//     // result => $link is red (but it should be blue)
//
// The fix:
//
//     // create a mixin that allows us to defer setting global defaults
//     @mixin init() {
//         $primary: red !default !global;
//         $link: darken($primary, 10%) !default !global;
//     }
//
//     $primary: blue;
//     @include init();
//
//    // result ==> $link is correctly derived from blue

@use 'utils' as *;
@use 'site' as *;
@use 'version' as *;

$-px-is-init: false;
$-px-version: str-split(get-version(), '.');
$-px-version-major: to-number(nth-if-length($-px-version, 1, 0));
$-px-version-minor: to-number(nth-if-length($-px-version, 2, 0));
$-px-version-patch: to-number(nth-if-length($-px-version, 3, 0));

/// Throws an error if px-styles hasn't been initialized by including the init mixin hasn't been
/// called / included. Checks are also provided for an optional minimum required version and an
/// optional configuration key that must be present.
///
/// This mixin is generally not required but there may be cases where components from different
/// libraries are each loading px-styles and this help to ensure that it has been initalized and
/// initialized with a compatible configuration.
///
/// @param {string} $require-min-version [null] A version number string consisting of three parts
/// separated by periods (e.g. 1.0.15) that represents the minimum required initialization version.
///
/// @param {string} $require-config-key [null] A configuration key (e.g. 'theme-projectname') that
/// must be set to a truthy value in the the config registry.
///
/// @example
/// %%include ensure-init($require-min-version: 1.0.0); // throws an error if initialized with verion 0.9.9
///
/// @example
/// %%include ensure-init($require-config-key: 'theme-projectname'); // throws an error if get('theme-projectname') isn't truthy

@mixin ensure-init($require-min-version: null, $require-config-key: null) {
    $is-init: $-px-is-init;

    @if not $is-init {
        @error 'Error: px-styles has not been correctly initialized. Make sure that the init() mixin has been called.';
    }

    // if provided, compare against the required version
    @if ($require-min-version) {
        $min-version: str-split($require-min-version, '.');
        $min-version-major: to-number(nth-if-length($min-version, 1, 0));
        $min-version-minor: to-number(nth-if-length($min-version, 2, 0));
        $min-version-patch: to-number(nth-if-length($min-version, 3, 0));

        $is-correct-version: true;
        $is-correct-version: $is-correct-version and ($-px-version-major >= $min-version-major);
        $is-correct-version: $is-correct-version and ($-px-version-minor >= $min-version-minor);
        $is-correct-version: $is-correct-version and ($-px-version-patch >= $min-version-patch);

        @if not $is-correct-version {
            @error 'Error: px-styles has not been initialized with a compatible version. Required minimum version is #{$require-min-version}. Initialized version is #{$-px-version}.';
        }
    }

    // if provided, ensure that the required config key has been defined
    @if ($require-config-key) {
        $config-key: get($require-config-key, 'NOTFOUND', false);
        @if $config-key == 'NOTFOUND' {
            @error 'Error: px-styles has not been initialized with the required configuration value for #{$require-config-key}.';
        }
    }
}

/// Initialize the library by filling in default values for all config values that haven't been
/// previously set using the `config` command. All defaults for all built-in modules are defined in
/// this mixin. This fixes a generalized loading problem and provides a single place to document all
/// possible defaults in a single location. See the source for details.
///
/// @example
/// // To initalize pxstyles, first add any required configuration
/// %%include config('colors:accent', #00dc82);
///
/// // then load the defaults by calling this mixin
/// %%include init();
///
/// @defaults

@mixin init() {
    // ----------------------------------------------------------------------------
    // Site
    // ----------------------------------------------------------------------------

    /// Base font size (set on the body, used for rems calculations)
    @include default('font-size-base', 15px);

    /// Global default value for spacing functions
    @include default('spacer', rems(12px));

    /// The total number of available shades in the shade and color functions (value of 20 produces a range of shades from -10, 10)
    @include default('shade-steps', 20);

    /// The default range for color shading
    @include default('shade-range', (black, white));

    /// Global default primary color. Optionally include a list of three values to override shading.
    @include default('colors:accent', #0099fd);

    /// Default base gray color. Optionally include a list of three values to override shading.
    @include default('colors:gray', (mix(#a0a0a0, accent(), 95%), accent(-9), white));

    /// Default text selection color
    @include default('colors:select', accent(-4));

    /// Default page background color
    @include default('colors:page-bg', white);

    /// Default page foreground
    @include default('colors:page-fg', gray(-7));

    /// Default light color used when computing contrast colors
    @include default('colors:contrast-light', clr(page-bg));

    /// Default light color used when computing contrast colors
    @include default('colors:contrast-dark', clr(page-fg));

    /// Default background color for selected text
    @include default('colors:selection-bg', clr(select));

    /// Default foreground color for selected text
    @include default('colors:selection-fg', contrast-color(clr(select)));

    // ----------------------------------------------------------------------
    // Typography
    // ----------------------------------------------------------------------

    /// _boilerplate_ A list of font faces that should be loaded by the `basics` mixin. Example of the
    /// syntax for this map:
    /// ```
    /// @include config('fonts', (
    ///
    ///     // google font
    ///     Inter: (googleFont: true, weight: 500, style: normal),
    ///
    ///     // local font
    ///     Circular: (src: '../assets/fonts/circular', weight: 500, style: normal)
    /// ));
    /// ```
    @include default('fonts', ());

    /// _boilerplate_ Default / fallback font family for the site
    @include default('font-family', sans-serif);

    /// _boilerplate_ Default / fallback font-weight for the site
    @include default('font-weight', 400);

    /// _boilerplate_ Whether to enable font-smoothing
    @include default('font-smoothing', true);

    /// _boilerplate_ Default code / mono font family (used as the default font for pre and code elements)
    @include default('code-font-family', (Menlo, Monaco, Consolas, monospace));

    /// _boilerplate_ Default code / mono font size (used as the default font for pre and code elements)
    @include default('code-font-size', rems(13px));

    /// _boilerplate_ Default / fallback line-height for standard text
    @include default('line-height', normal);

    /// _boilerplate_ Default / fallback letter spacing for the site
    @include default('letter-spacing', normal);

    /// _boilerplate_ Use this to automatically adjust font size on the body (and therefore also as the
    /// basis for rems units) based on media queries. The value is a map that contains media query
    /// breaks and inputs into the `fs()` function for retrieving a font-size. prettier-ignore
    @include default(
        'font-size-breaks',
        (
            md: -1,
        )
    );

    /// A map of standard named font sizes. At least one size must be named 'base' which should
    /// correspond to base-font-size.
    @include default(
        'type-scale',
        (
            'xxs': 11px,
            'xs': 13px,
            'sm': 14px,
            // will throw an error if not defined
            'base': get('font-size-base'),
            'md': 18px,
            'lg': 20px,
            'xl': 24px,
            'h4': 28px,
            'h3': 36px,
            'h2': 42px,
            'h1': 54px,
            'd2': 60px,
            'd1': 72px,
        )
    );

    /// A set of type style base styles. These styles are never actually generated, but other type
    /// styles can be derived from them with `type-style` mixin (which takes a map of additional css
    /// properties or overrides). Note: individual settings can be configured using flat map syntax.
    @include default(
        'type-bases',
        (
            headings: (
                font-family: null,
                font-weight: 700,
                line-height: 1,
                letter-spacing: null,
                color: null,
                margin-top: 0.75em,
                margin-bottom: 0.75em,
            ),
            sub-headings: (
                font-family: null,
                font-weight: null,
                line-height: 1.15,
                letter-spacing: null,
                color: null,
                margin-bottom: 0.5em,
            ),
            code: (
                font-family: get('code-font-family'),
                font-size: get('code-font-size'),
                font-weight: 400,
                line-height: 1.4,
            ),
        )
    );

    /// _boilerplate_ Full set of type styles that should be generated based. Each entry requires a
    /// `base` property which is a lookup into `type-bases`.
    @include default(
        'type-styles',
        (
            '.display1': (
                font-size: fs(7),
                -base: 'headings',
            ),
            '.display2': (
                font-size: fs(6),
                -base: 'headings',
            ),
            '.h1': (
                font-size: fs(5),
                -base: 'headings',
            ),
            '.h2': (
                font-size: fs(4),
                -base: 'headings',
            ),
            '.h3': (
                font-size: fs(3),
                -base: 'headings',
            ),
            '.h4': (
                font-size: fs(2),
                -base: 'headings',
            ),
            '.h5': (
                font-size: fs(1),
                -base: 'headings',
            ),
            '.sh1': (
                font-size: fs(2),
                -base: 'sub-headings',
            ),
            '.sh2': (
                font-size: fs(1),
                -base: 'sub-headings',
            ),
            '.sh3': (
                font-size: fs(0),
                -base: 'sub-headings',
            ),
        )
    );

    // ----------------------------------------------------------------------
    // Media Queries
    // ----------------------------------------------------------------------

    /// Named breakpoints that can be used by the standard mediaquery mixins
    /// (e.g. `media-until(md) {...}`).
    @include default(
        'breakpoints',
        (
            xs: 640px,
            mobile: 768px,
            sm: 1024px,
            md: 1366px,
            lg: 1600px,
            xl: 1920px,
        )
    );

    /// The standardized breakpoint where a mobile version of the design begins. Used by the mixin
    /// `@media-until-mobile() {...}`.
    @include default('mobile-breakpoint', 'mobile');

    // ----------------------------------------------------------------------
    // Transitions
    // ----------------------------------------------------------------------

    /// Collection of named transitions. The keys in this map can be used as the second argument in
    /// the `transition` mixin to help create consistent css transitions.  Note: individual settings
    /// can be configured using flat map syntax.
    @include default(
        'transitions',
        (
            default: (
                dur: 150ms,
                ease: $ease-out-quart,
            ),
            fast: (
                dur: 75ms,
                ease: $ease-out-quart,
            ),
            slow: (
                dur: 300ms,
                ease: $ease-out-quart,
            ),
            none: (
                dur: 0,
                ease: null,
            ),
        )
    );

    // ----------------------------------------------------------------------
    // Shadows
    // ----------------------------------------------------------------------

    /// _shadows_ Number of distinct levels for both parameters ($depth, $color) of the
    /// standardized shadow function / mixin.
    @include default('shadows:levels', 20);

    /// _shadows_ Color or range for the standardized shadow.
    @include default('shadows:color', black);

    /// _shadows_ Dark portion of the key shadow in the 'depth-shadow' mixin. Note: individual properties can
    /// be configured using flat-map syntax.
    // prettier-ignore
    @include default(
        'shadows:umbra',
        (
            y: ( 0px, 12px ),
            blur: (0px, 20px),
            spread: (0px, -7px),
            opacity: (0.2, 0.3),
        )
    );

    /// _shadows_ Soft portion of the key shadow in the 'depth-shadow' mixin. Note: individual properties can
    /// be configured using flat-map syntax.
    // prettier-ignore
    @include default(
        'shadows:penumbra',
        (
            y: (1px, 24px),
            blur: (0px, 38px),
            spread: (0px, 0px),
            opacity: (0, 0.15),
        )
    );

    /// _shadows_ Ambient light portion of the shadow in the 'depth-shadow' mixin. Note: individual properties
    /// can be configured using flat-map syntax.
    // prettier-ignore
    @include default(
        'shadows:ambient',
        (
            y: (0px, 9px ),
            blur: (0px, 50px),
            spread: (0px, 8px),
            opacity: (0.05, 0.15),
        )
    );

    // ----------------------------------------------------------------------
    // Site Basics
    // ----------------------------------------------------------------------

    // container

    /// _boilerplate_ Settings related to the default outer content container. Note: individual settings
    /// can be configured using flat map syntax.
    @include default(
        'container',
        (
            width: 1200px,
            gutter: sp(3),
            selector: '.container',
        )
    );

    //  resets

    /// _boilerplate_ Settings related to the default outer content container. Note: individual settings
    /// can be configured using flat map syntax.
    @include default(
        'reset',
        (
            sanitize: true,
            link: true,
            button: true,
            lists: true,
            headings: true,
            paragraph: true,
        )
    );

    // links

    /// _boilerplate_ Setings related to the default rendering of hyperlinks.
    @include default(
        'links',
        (
            -selector: '.link',
            color: adjust-color(accent(), $saturation: 40%),
            text-decoration: none,
            text-decoration-color: null,
            hover: (
                color: null,
                background-color: rgba(accent(), 0.1),
                text-decoration: underline,
                text-decoration-color: null
            )
        )
    );

    // ----------------------------------------------------------------------
    // Reading
    // ----------------------------------------------------------------------

    // reading: default styles (css map)
    // @include default(
    //     'reading',
    //     (
    //         base: (
    //             font-family: get('font-family'),
    //             font-size: fs(base),
    //             line-height: normal,
    //             font-weight: 400,
    //         ),
    //     )
    // );

    // reading: font weight for <strong> text
    @include default('reading:font-weight-strong', 600);

    // reading: default vertical spacing between block elements (set as a margin-bottom)
    @include default('reading:blocks', (p, iframe, ul, ol, form, section, table, pre));
    @include default('reading:block-spacing', 1em);

    // reading: list / list item (li) customization
    @include default('reading:list-padding', 1.25em);
    @include default('reading:list-item-padding', 0.25em);
    @include default('reading:list-item-spacing', 0.25em);

    // reading: links
    @include default(
        'reading:links',
        flat-merge(
            get('links'),
            (
                text-decoration: underline,
            )
        )
    );

    // reading: type styles
    @include default('reading:styles-base', 'headings');
    @include default(
        'reading:styles',
        (
            'h1, .h1': (
                'font-size': fs(5),
            ),
            'h2, .h2': (
                'font-size': fs(4),
            ),
            'h3, .h3': (
                'font-size': fs(3),
            ),
            'h4, .h4': (
                'font-size': fs(2),
            ),
            'h5, .h5': (
                'font-size': fs(1),
            ),
        )
    );

    // ----------------------------------------------------------------------
    // Controls
    // ----------------------------------------------------------------------

    @include default(
        'controls',
        (
            accent: accent(),
            border-radius: 3px,
            font-family: get(font-family),
            font-size: fs(base),
            font-weight: 400,
            min-height: 2.25em,
            min-width: 6em,
        )
    );

    @include default(
        'focus',
        (
            selector: ':focus-visible',
            shadow-color: accent($alpha: 0.33),
            shadow-width: 3px,
        )
    );

    // @include default(
    //     'controls:base',
    //     (
    //         -px-accent: accent(),
    //         -px-radius: 3px,
    //         -px-focus-style: 'shadow',
    //         -px-transition: 'fast',
    //         min-height: 2.25em,
    //         line-height: 1.33,
    //         font-family: get('font-family'),
    //         font-size: fs(base),
    //         font-weight: 400
    //     )
    // );

    // textbox

    // @include default(
    //     'controls:textbox',
    //     (
    //         -px-accent: accent(),
    //         -px-placeholder: rgba(clr('page-fg'), 0.5),
    //         border: none,
    //         background-color: rgba(gray(7), 0.66),
    //         color: clr('page-fg'),
    //         min-height: 2.25em,
    //         min-width: 6em,
    //         padding: 0 0.5em,
    //         hover: (),
    //         disabled: (),
    //         read-only: ()
    //     )
    // );

    @include default(
        'controls:slider',
        (
            track-height: 4px,
            track-max-width: 200px,
            track-radius: 2px,
            track-bg: gray(5),
            track-border: none,
            track-shadow: null,
            thumb-bg: accent(),
            thumb-border: none,
            thumb-width: 12px,
            thumb-height: 12px,
            thumb-radius: 50%,
            thumb-px-shadow: shadow(2),
        )
    );

    // checkbox

    // prettier-ignore
    @include default(
        'controls:checkbox',
        (
            // toggle-width: 16px,
            // toggle-height: 16px,
            // toggle-spacing: 6px,
            // toggle-side: left,
            // toggle-background: inline-svg('<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg"><rect width="18" height="18" rx="2" fill="--fill" fill-rule="evenodd"/></svg>', (--fill: gray(6))),
            // toggle-background-hover:inline-svg('<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg"><rect width="18" height="18" rx="2" fill="--fill" fill-rule="evenodd"/></svg>',(--fill: gray(3))),
            // toggle-check: inline-svg('<svg width="18" height="18" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg"><path d="M3.7 9.7L7 13l7.3-7.3" stroke="--stroke" stroke-width="2.5" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round"/></svg>',(--stroke: get('controls:base:-px-accent'))),
            // toggle-indeterminate: inline-svg('<svg width="18" height="18" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg"><rect x="5" y="5" width="8" height="8" rx="1" fill="--fill" fill-rule="evenodd"/></svg>',(--fill: get('controls:base:-px-accent')))
        )
    );

    // radio

    // prettier-ignore
    @include default(
        'controls:radio',
        (
            // toggle-width: 16px,
            // toggle-height: 16px,
            // toggle-spacing: 6px,
            // toggle-side: left,
            // toggle-background: inline-svg('<svg width="18" height="18" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg"><circle cx="9" cy="9" r="8.5" fill="--fill" stroke="--stroke" fill-rule="evenodd"/></svg>', (--fill: gray(5), --stroke: gray())),
            // toggle-background-hover: inline-svg('<svg width="18" height="18" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg"><circle cx="9" cy="9" r="8.5" fill="--fill" stroke="--stroke" fill-rule="evenodd"/></svg>', (--fill: gray(3), --stroke: gray())),
            // toggle-check:inline-svg('<svg width="18" height="18" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg"><circle cx="9" cy="9" r="5" fill="--fill" fill-rule="evenodd"/></svg>',(--fill: get('controls:base:-px-accent')))
        )
    );

    // toggle

    // prettier-ignore
    @include default(
        'controls:toggle',
        (
            // toggle-width: 38px,
            // toggle-height: 19px,
            // toggle-spacing: 6px,
            // toggle-side: left,
            // toggle-shadow: null, //inset 0 1px 0px rgba(black, 0.2),
            // toggle-off-background: gray(4),
            // toggle-off-background-hover:null,
            // toggle-off-background-active: gray(2),
            // toggle-on-background: accent(),
            // toggle-on-background-hover: null,
            // toggle-on-background-active: accent(-1),
            // indicator-gap: 2px,
            // indicator-aspect: 1,
            // indicator-off-background: gray(8),
            // indicator-on-background: white,
            // indicator-shadow: 0px 2px 5px 0px rgba(black, 0.25)
        )
    );

    // toggle-button

    @include default(
        'controls:toggle-button',
        (
            // -px-accent: gray(10),
            // -px-shadow: shadow(1),
            // -px-icon: inline-svg(
            //         '<svg width="10" height="8" viewBox="0 0 10 8" xmlns="http://www.w3.org/2000/svg"><path stroke="--stroke" stroke-width="2" d="m1 3.256 2.755 2.863L8.875 1" fill="none" fill-rule="evenodd"/></svg>',
            //         (
            //             --stroke: rgba(white, 0.66),
            //         )
            //     ),
            // -px-icon-width: 0.7em,
            // -px-icon-height: 1em,
            // -px-icon-space: 0.3em,
            // -px-connect: false,
            // font-size: fs(sm),
            // min-height: 2em,
            // min-width: initial,
            // padding: 0 1.25em,
            // border: 1px solid gray(),
            // color: gray(-6),
            // hover: (-px-accent: gray(10), border: 1px solid clr(select), -px-shadow: shadow(2)),
            // active: (
            //     -px-accent: clr(select, -1),
            //     color: contrast-color(select),
            //     border: 1px solid clr(select, -3)
            // ),
            // checked: (
            //     -px-accent: clr(select),
            //     color: contrast-color(select),
            //     border: 1px solid clr(select, -4),
            //     hover: (border: 1px solid clr(select, -4)),
            //     active: (-px-accent: clr(select, 2))
            //)
        )
    );

    // tooltip

    @include default(
        'controls:tooltip',
        (
            // background-color: #fae9c8,
            // border: 1px solid #e3ba71,
            // font-size: rems(13px),
            // max-width: 40em,
            // min-height: 1.75em,
            // display: flex,
            // align-items: center,
            // padding: 0 0.75em,
            // border-radius: get('controls:base:-px-radius'),
        )
    );

    // flag as initialized
    $-px-is-init: true !global;
}

// @include default(
//     'controls:dropdown',
//     (
//         cursor: pointer,
//         padding: 0 0.5em,
//         icon:
//             '<svg width="8" height="5" xmlns="http://www.w3.org/2000/svg"><path fill="#fill" d="M0 0h8L4 5z" fill-rule="evenodd"/></svg>',
//         icon-fill: 3 // accent: accent(),
//             // bg: gray(6),
//             // fg: null,
//             // placeholder: null,
//             // height: null,
//             // border: none,
//             // min-width: 6em,
//             // padding: 0 0.5em,
//             // disabled: (
//             //     bg: 7,
//             //     fg: 4,
//             //     placeholder: 6,
//             //     border: none,
//             //     icon: null,
//             //     icon-fill: null,
//             // ),
//             // readonly: (
//             //     bg: 1,
//             //     fg: 0,
//             //     placeholder: 0,
//             //     border: none,
//             //     icon:
//             //         '<svg width="9" height="11" xmlns="http://www.w3.org/2000/svg"><path d="M4.5 0a3 3 0 013 3v1h1a.5.5 0 01.5.5v6a.5.5 0 01-.5.5h-8a.5.5 0 01-.5-.5v-6A.5.5 0 01.5 4h1V3a3 3 0 013-3zm0 1.5a1.5 1.5 0 00-1.493 1.356L3 3v1h3V3a1.5 1.5 0 00-1.5-1.5z" fill="#fill" fill-rule="evenodd"/></svg>',
//             //     icon-fill: 5,
//             // ),,,
//     )
// );
