<template>
    <component
        :is="tag"
        :class="
            bem({
                ...variantsMap,
                checked: toggles && checkedValue,
                unchecked: toggles && !checkedValue,
            })
        "
        @click="tryToggleChecked"
    >
        <px-icon :class="iconClass" v-bind="calcIconAttrs" />
    </component>
</template>

<script>
import { PxIcon, PxIconSrcOrAttrs, PxIconPropsFilter } from './PxIcon.vue';
import PxBase from '../bases/PxBase.vue';
import PxBaseToggle from '../bases/PxBaseToggle.vue';

export default {
    name: 'px-icon-button',
    mixins: [PxBase, PxBaseToggle],
    components: { PxIcon },
    props: {
        /**
         * A string that either represents the key (name) of an app-level icon or the svg src for
         * the icon. Note that this is equivalent to setting the icon prop with ="{src: '...'}"
         */
        src: { type: [String, Object], default: null },

        /**
         * A string that either represents the key (name) of an app-level icon or the svg src for
         * the icon. Note that this is equivalent to setting the iconChecked prop with ="{src: '...'}"
         */
        srcChecked: { type: [String, Object], default: null },

        /**
         * Provide a default value for the size of the icon. This is equivalent to setting the size
         * using the icon property with icon="{src:'...', size: '...'}"
         */
        size: { type: [Number, String], default: null },

        /**
         * The icon to display. If a string is provided, it will be interpreted as the src of the
         * icon. If an object is provided, it will be passed directly to the icon component as
         * props (with a filter applied to ensure no fallback attributes).
         */
        icon: { type: [String, Object], default: null },

        /**
         * The icon to display when the button is a checked state (assuming toggles is true).
         * If a string is provided, it will be interpreted as the src of the icon. If an object is
         * provided, it will be passed directly to the icon component as props (with a filter
         * applied to ensure no fallback attributes).
         */
        iconChecked: { type: [String, Object], default: null },

        /**
         * Whether the checked icon should inherit the size and other attributes of the normal icon.
         */
        iconCheckedInherits: { type: Boolean, default: true },

        /**
         * Set this to true to enable toggling on the button (see PxBaseToggle for details).
         **/
        toggles: { type: Boolean, default: false },

        iconClass: { type: String, default: null },

        tag: { type: String, default: 'button' },
    },
    computed: {
        calcIcon() {
            if (!this.icon) {
                return {
                    src: this.src,
                    size: this.size || 1,
                };
            }

            return PxIconSrcOrAttrs(this.icon);
        },

        calcIconChecked() {
            let attrs = {};

            if (!this.iconChecked) {
                attrs = { src: this.srcChecked };
            } else {
                if (typeof this.iconChecked === 'string') {
                    attrs = {
                        src: this.iconChecked,
                    };
                } else {
                    attrs = this.iconChecked;
                }
            }

            attrs = {
                ...(this.iconCheckedInherits ? this.calcIcon : { size: this.size || 1 }),
                ...attrs,
            };

            return PxIconPropsFilter(attrs);
        },

        calcIconAttrs() {
            if (this.toggles && this.calcIconChecked && this.checkedValue) {
                return this.calcIconChecked;
            }
            return this.calcIcon;
        },
    },
    methods: {
        tryToggleChecked() {
            if (this.toggles) {
                this.toggleChecked();
            }
        },
    },
};
</script>

<style lang="scss">
@use '../styles/px.scss' as *;
@use '@thinkpixellab-public/px-styles/src/modules/controls' as controls;

.px-icon-button {
    // VARIANTS

    @include controls.control-reset();

    &--default {
        @include controls.button-icon(
            (
                padding: 0,
                min-height: 0,
            )
        );
        @include focus() {
            outline: 1px dashed currentColor;
        }
    }

    &--toggles.px-icon-button--unchecked {
        opacity: 0.5;
        &:hover {
            opacity: 0.66;
        }
    }

    &--basic {
        @include controls.control-reset();
        background-color: transparent;
        min-width: 0;
        min-height: 0;
        background-color: transparent;
        padding: 0;
        border-radius: 0.05em;
        line-height: 1;
        @include focus() {
            outline-offset: 0.1em;
            outline: 1px dotted currentColor;
        }
        cursor: pointer;
    }

    &--accent {
        color: accent();
    }

    &--white {
        color: white;
    }

    &--accent-hover {
        @include transition(transform color);
        &:hover {
            color: accent(2);
        }
        &:active {
            color: accent(-2);
        }
    }

    &--subtle {
        opacity: 0.33;
        &:hover {
            opacity: 1;
        }
    }
}
</style>
