<template>
    <component :is="is" :class="componentClass" :target="target" href="href" aria-label="ariaLabel" aria-pressed="pressed"
        :disabled="disabled" :type="type" v-on:click="click">

        <span class="button-vue__wrapper">
            <!-- <span v-if="hasIcon" class="button-vue__icon" aria-hidden="true">
            {{ this.$slots.icon }}-->
            <BaseIcon v-if="icon" :path="icon" class="button-vue__icon" aria-hidden="true" :size="size" />

            <!-- <span v-if="hasText" class="button-vue__text">{{ this.$slots.default }}</span> -->
            <span v-if="label" class="font-bold whitespace-nowrap text-ellipsis overflow-hidden" :class="labelClass">{{
                label }}</span>
        </span>
    </component>
</template>
<script lang="ts">
import BaseIcon from '@/Components/BaseIcon.vue';
// import { h } from 'vue';
export default {
    name: 'NcButton',

    components: {
        BaseIcon
    },

    props: {
        size: {
            type: [String, Number],
            default: 16,
        },
        small: Boolean,
        roundedFull: {
            type: Boolean,
            default: false,
        },
        label: {
            type: [String, Number],
            default: null,
        },
        icon: {
            type: String,
            default: null,
        },
        /**
         * Set the text and icon alignment
         *
         * @default 'center'
         */
        alignment: {
            type: String,
            default: 'center',
            validator: (alignment: string) => ['start', 'start-reverse', 'center', 'center-reverse', 'end', 'end-reverse'].includes(alignment),
        },

        /**
         * Toggles the disabled state of the button on and off.
         */
        disabled: {
            type: Boolean,
            default: false,
        },

        /**
         * Specifies the button type
         * Accepted values: primary, secondary, tertiary, tertiary-no-background, tertiary-on-primary, error, warning, success. If left empty,
         * the default button style will be applied.
         */
        type: {
            type: String,
            validator(value: string) {
                return (
                    [
                        'primary',
                        'secondary',
                        'tertiary',
                        'tertiary-no-background',
                        'tertiary-on-primary',
                        'error',
                        'warning',
                        'success',
                    ].indexOf(value) !== -1
                );
            },
            default: 'secondary',
        },

        /**
         * Specifies the button native type
         * Accepted values: submit, reset, button. If left empty,
         * the default "button" type will be used.
         */
        nativeType: {
            type: String,
            validator(value: string) {
                return ['submit', 'reset', 'button'].indexOf(value) !== -1;
            },
            default: 'button',
        },

        /**
         * Specifies whether the button should span all the available width.
         * By default, buttons span the whole width of the container.
         */
        wide: {
            type: Boolean,
            default: false,
        },

        /**
         * Always try to provide an aria-label to your button. Make it more
         * specific than the button's name by provide some more context. E.g. if
         * the name of the button is "send" in the Mail app, the aria label could
         * be "Send email".
         */
        ariaLabel: {
            type: String,
            default: null,
        },

        /**
         * Providing the href attribute turns the button component into an `a`
         * element.
         */
        href: {
            type: String,
            default: null,
        },

        /**
         * Providing the download attribute with href downloads file when clicking.
         */
        download: {
            type: String,
            default: null,
        },

        /**
         * Providing the to attribute turns the button component into a `router-link`
         * element. Takes precedence over the href attribute.
         */
        to: {
            type: [String, Object],
            default: null,
        },

        /**
         * Pass in `true` if you want the matching behaviour of `router-link` to
         * be non-inclusive: https://router.vuejs.org/api/#exact
         */
        exact: {
            type: Boolean,
            default: false,
        },
        /**
         * @deprecated To be removed in @nextcloud/vue 9. Migration guide: remove ariaHidden prop from NcAction* components.
         * @todo Add a check in @nextcloud/vue 9 that this prop is not provided,
         * otherwise root element will inherit incorrect aria-hidden.
         */
        ariaHidden: {
            type: Boolean,
            default: null,
        },

        /**
         * The pressed state of the button if it has a checked state
         * This will add the `aria-pressed` attribute and for the button to have the primary style in checked state.
         */
        pressed: {
            type: Boolean,
            default: null,
        },
    },

    emits: ['update:pressed', 'click'],

    computed: {
        labelClass() {
            return (this.small && this.icon) ? 'px-1' : 'px-2';
        },
        is() {
            if (this.href) {
                return 'a';
            }
            return 'button';
        },
        hasText() {
            // return !!this.$slots.default;
            return this.label != undefined;
        },
        hasIcon() {
            // return this.$slots?.icon;
            return this.icon != undefined;
        },
        // type() {
        // return this.href ? null : this.nativeType;
        // },

        componentClass() {
            const base = [
                'button-vue',
                this.roundedFull ? 'rounded-full' : 'rounded',
                'inline-flex',
                'cursor-pointer',
                'justify-center',
                'items-center',
                'whitespace-nowrap',
                'focus:outline-none',
                'transition-colors',
                // 'focus:ring-2',
                {
                    'button-vue--icon-only': this.hasIcon && !this.hasText,
                    'button-vue--text-only': this.hasText && !this.hasIcon,
                    'button-vue--icon-and-text': this.hasIcon && this.hasText,
                    [`button-vue--vue-${this.realType}`]: this.realType,
                    'button-vue--wide': this.wide,
                    [`button-vue--${this.flexAlignment}`]: this.flexAlignment !== 'center',
                    'button-vue--reverse': this.isReverseAligned,
                    // Add other classes based on conditions as needed


                },
            ];
            if (this.small) {
                base.push('text-sm', this.roundedFull ? 'px-3 py-1' : 'p-1');
            } else {
                base.push('py-2', this.roundedFull ? 'px-6' : 'px-3');
            }
            return base;
        },

        target() {
            return (!this.to && this.href) ? '_self' : null;
        },

        /**
         * The real type to be used for the button, enforces `primary` for pressed state and, if stateful button, any other type for not pressed state
         * Otherwise the type property is used.
         */
        realType() {
            // Force *primary* when pressed
            if (this.pressed) {
                return 'primary';
            }
            // If not pressed but button is configured as stateful button then the type must not be primary
            if (this.pressed === false && this.type === 'primary') {
                return 'secondary';
            }
            return this.type;
        },

        /**
         * The flexbox alignment of the button content
         */
        flexAlignment() {
            return this.alignment.split('-')[0];
        },

        /**
         * If the button content should be reversed (icon on the end)
         */
        isReverseAligned() {
            return this.alignment.includes('-');
        },
    },

    methods: {
        click($event) {
            // Update pressed prop on click if it is set
            if (typeof this.pressed === 'boolean') {
                /**
                 * Update the current pressed state of the button (if the `pressed` property was configured)
                 *
                 * @property {boolean} newValue The new `pressed`-state
                 */
                this.$emit('update:pressed', !this.pressed)
            }
            // We have to both navigate and emit the click event
            this.$emit('click', $event)
            // navigate?.($event)
        },
    },




};
</script>

<style lang="css" scoped>
.button-vue {
    position: relative;
    
    /* width: fit-content;
    overflow: hidden;
    border: 0; */
    padding: 0;
    /* font-size: var(--default-font-size);
    font-weight: bold; */
    min-height: 44px;
    min-width: 44px;
    display: flex;
    align-items: center;
    /* justify-content: center; */

    /* Cursor pointer on element and all children */
    cursor: pointer;

    & *,
    span {
        cursor: pointer;
    }

    /* border-radius: math.div($clickable-area, 2); */
    /* transition-property: color, */
    /* border-color,
    background-color;
    transition-duration: 0.1s;
    transition-timing-function: linear; */

    /* border-radius: math.div($clickable-area, 2); */
    /* border-radius: calc(50% - var(--clickable-area) / 2);
	transition-property: color, border-color, background-color;
	transition-duration: 0.1s;
	transition-timing-function: linear; */

    /* No outline feedback for focus. Handled with a toggled class in js (see data) */
    &:focus {
        outline: none;
    }

    &:disabled {
        cursor: default;

        & * {
            cursor: default;
        }

        opacity: 0.5;
        /* // Gives a wash out effect */
        filter: saturate(0.7l);
    }

    /* // Default button type */
    color: var(--color-primary-element-light-text);
    background-color: var(--color-primary-element-light);

    &:hover:not(:disabled) {
        background-color: var(--color-primary-element-light-hover);
    }


    /* Back to the default color for this button when active */
    /* TODO: add ripple effect  */
    &:active {
        background-color: var(--color-primary-element-light);
    }

    &__wrapper {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 100%;
    }

    &--end &__wrapper {
        justify-content: end;
    }

    &--start &__wrapper {
        justify-content: start;
    }

    &--reverse &__wrapper {
        flex-direction: row-reverse;
    }

    &--reverse &--icon-and-text {
        padding-inline: calc(var(--default-grid-baseline) * 4) var(--default-grid-baseline);
    }

    &__icon {
        height: 44px;
        width: 44px;
        min-height: 44px;
        min-width: 44px;
        display: flex;
        justify-content: center;
        align-items: center;
    }

    /* &__text {
        font-weight: bold;
        margin-bottom: 1px;
        padding: 2px 0;
        white-space: nowrap;
        text-overflow: ellipsis;
        overflow: hidden;
    } */

    /* Icon-only button */
    &--icon-only {
        width: 44px !important;
    }

    /* Text-only button */
    &--text-only {
        padding: 0 12px;

        & .button-vue__text {
            margin-left: 4px;
            margin-right: 4px;
        }
    }

    /* Icon and text button */
    &--icon-and-text {
        padding-block: 0;
        padding-inline: var(--default-grid-baseline) calc(var(--default-grid-baseline) * 4);
    }

    /* Wide button spans the whole width of the container */
    &--wide {
        width: 100%;
    }

    &:focus-visible {
        outline: 2px solid var(--color-main-text) !important;
        box-shadow: 0 0 0 4px var(--color-main-background) !important;

        &.button-vue--vue-tertiary-on-primary {
            outline: 2px solid var(--color-primary-element-text);
            border-radius: var(--border-radius);
            background-color: transparent;
        }
    }

    /* Button types */

    /* // Primary */
    &--vue-primary {
        background-color: var(--color-primary-element);
        color: var(--color-primary-element-text);

        &:hover:not(:disabled) {
            background-color: var(--color-primary-element-hover);
        }

        /* Back to the default color for this button when active
        TODO: add ripple effect */
        &:active {
            background-color: var(--color-primary-element);
        }
    }

    /* Secondary */
    &--vue-secondary {
        color: var(--color-primary-element-light-text);
        background-color: var(--color-primary-element-light);

        &:hover:not(:disabled) {
            color: var(--color-primary-element-light-text);
            background-color: var(--color-primary-element-light-hover);
        }
    }

    /* Tertiary */
    &--vue-tertiary {
        color: var(--color-main-text);
        background-color: transparent;

        &:hover:not(:disabled) {
            background-color: var(--color-background-hover);
        }
    }

    /* Tertiary, no background */
    &--vue-tertiary-no-background {
        color: var(--color-main-text);
        background-color: transparent;

        &:hover:not(:disabled) {
            background-color: transparent;
        }
    }

    /* Tertiary on primary color (like the header) */
    &--vue-tertiary-on-primary {
        color: var(--color-primary-element-text);
        background-color: transparent;

        &:hover:not(:disabled) {
            background-color: transparent;
        }
    }

    /* Success */
    &--vue-success {
        background-color: var(--color-success);
        color: white;

        &:hover:not(:disabled) {
            background-color: var(--color-success-hover);
        }

        /* Back to the default color for this button when active
        : add ripple effect */
        &:active {
            background-color: var(--color-success);
        }
    }

    /* Warning */
    &--vue-warning {
        background-color: var(--color-warning);
        color: white;

        &:hover:not(:disabled) {
            background-color: var(--color-warning-hover);
        }

        /* Back to the default color for this button when active
        TODO: add ripple effect */
        &:active {
            background-color: var(--color-warning);
        }
    }

    /* Error */
    &--vue-error {
        background-color: var(--color-error);
        color: white;

        &:hover:not(:disabled) {
            background-color: var(--color-error-hover);
        }

        /* Back to the default color for this button when active
        TODO: add ripple effect */
        &:active {
            background-color: var(--color-error);
        }
    }
}
</style>
