<template>
    <div class="hy-button" :style="{ maxWidth: extend ? '' : 'max-content' }" :class="{ transitionsEnabled }">
        <button :class="[variantParsed, sizeParsed, { hideText: loading, isGhost, isGhostBg, isSolid }]" :disabled="disabled || loading">
            <slot />
        </button>

        <transition name="hy-fade-transition">
            <HyLoader v-if="loading && progress == null" :width="25" :height="25" :line="3" />
        </transition>
        <transition name="hy-fade-transition">
            <HyProgressBar
                v-if="loading && isNaN(progress) == false && typeof progress == 'number'"
                :progress="progress"
                :width="progressWidth"
            />
        </transition>
    </div>
</template>

<script>
import HyLoader from "./Loader.vue";
import HyProgressBar from "./ProgressBar.vue";

export default {
    name: "HyButton",
    props: {
        variant: {
            type: String,
            default: null,
        },
        size: {
            type: String,
            default: null,
        },
        loading: {
            type: Boolean,
            default: false,
        },
        progress: {
            type: Number,
            default: null,
        },
        progressWidth: {
            type: String,
            default: "min(calc(100% - 2 * var(--hy-element-padding)), 200px)",
        },
        disabled: {
            type: Boolean,
            default: false,
        },
        extend: {
            type: Boolean,
            default: true,
        },
    },
    data() {
        return {
            brandThemeStyles: "",
            transitionsEnabled: false,
        };
    },
    computed: {
        sizeParsed() {
            let size = this.size ?? this.hy_defaults.size;
            let allowed = ["lg", "md", "sm"];

            if (allowed.includes(size)) return `size-${size}`;
            else return "size-lg";
        },
        variantParsed() {
            let allowed = [...this.hy_brand_theme.availableVariants, "secondary", "ghost", "ghost-bg"];
            let variant = this.variant ?? this.hy_defaults.variant;

            if (allowed.includes(variant)) return variant;
            else return "secondary";
        },
        isGhostBg() {
            return this.variantParsed.startsWith("ghost-bg");
        },
        isGhost() {
            return this.variantParsed.startsWith("ghost") && this.variantParsed.startsWith("ghost-bg") == false;
        },
        isSolid() {
            return this.variantParsed.startsWith("ghost") == false && this.variantParsed.startsWith("ghost-bg") == false;
        },
        fontColor() {
            // Note: "ghost" and "ghost-bg" variants share the same variables => trim the "-bg" part
            return `var(--hy-variant-${this.variantParsed.replace("-bg", "")}-font-color)`;
        },
        backgroundColor() {
            return `var(--hy-variant-${this.variantParsed.replace("-bg", "")}-bg-color)`;
        },
        hoverColor() {
            return `var(--hy-variant-${this.variantParsed.replace("-bg", "")}-hover-color)`;
        },
        borderColor() {
            return `var(--hy-variant-${this.variantParsed.replace("-bg", "")}-border-color)`;
        },
        borderColorPressed() {
            if (this.isSolid == false) return "transparent";
            else return `var(--hy-variant-${this.variantParsed.replace("-bg", "")}-border-color-pressed)`;
        },
    },
    mounted() {
        requestAnimationFrame(() => (this.transitionsEnabled = true));
    },
    components: {
        HyLoader,
        HyProgressBar,
    },
};
</script>

<style lang="scss">
.hy-button {
    margin: var(--hy-element-margin);
    position: relative;
    min-width: max-content;

    &.transitionsEnabled {
        button {
            transition: var(--hy-element-transition);
            transition-property: background-color, color, border, filter;
        }
    }

    button {
        -moz-appearance: none;
        -webkit-appearance: none;
        appearance: none;

        width: 100%;
        border-radius: var(--hy-element-border-radius);
        font-size: var(--hy-font-size);
        font-family: var(--hy-font-family);
        font-weight: bold;
        cursor: pointer;

        &:disabled {
            cursor: not-allowed;
            filter: opacity(50%);

            * {
                pointer-events: none;
            }
        }

        &.hideText {
            color: transparent !important;
        }

        // Sizes
        &.size-lg {
            padding: var(--hy-element-padding);
        }

        &.size-md {
            padding: var(--hy-element-padding-md);
        }

        &.size-sm {
            padding: var(--hy-element-padding-sm);
        }

        // Brand theme variants
        border: 2px solid transparent; // TODO: make border width a CSS variable
        color: v-bind(fontColor);

        &.isSolid {
            box-shadow: var(--hy-element-shadow);
            border-color: v-bind(borderColor); // Solids always have a border
            background-color: v-bind(backgroundColor); // Solids always have a background

            &:not([disabled]) {
                &:hover {
                    background-color: v-bind(hoverColor);
                }

                &:focus,
                &:active {
                    border-color: v-bind(borderColorPressed);
                }
            }
        }

        &.isGhost,
        &.isGhostBg {
            &:not([disabled]) {
                &:focus,
                &:active {
                    border-color: v-bind(borderColor);
                }
            }

            &.hideText {
                background-color: v-bind(backgroundColor); // Show background color if hideText is set (e.g. loading is active)
            }
        }

        &.isGhost {
            background-color: transparent;

            &:not([disabled]):hover {
                background-color: v-bind(backgroundColor);
            }
        }

        &.isGhostBg {
            background-color: v-bind(backgroundColor);

            &:not([disabled]):hover {
                background-color: v-bind(hoverColor);
            }
        }
    }

    .hy-loader {
        position: absolute;
        top: calc(50% - 12.5px);
        left: calc(50% - 12.5px);
    }

    .hy-progress-bar {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
    }
}
</style>
