// directives/intersectionTransition.ts
import { Directive } from 'vue'

interface TransitionOptions {
    type?: string
    duration?: number | string
    easing?: string
    delay?: number | string
    opacity?: number | string
    transform?: string
    threshold?: number
}

interface IntersectionElement extends HTMLElement {
    _observer?: IntersectionObserver
    _options?: TransitionOptions
}

function setupTransition(el: IntersectionElement, binding: any) {
    // Handle different binding value types
    let options: TransitionOptions = {}

    if (typeof binding.value === 'string') {
        // Simple string usage: v-show-on-intersect="'fade-up'"
        options = { type: binding.value }
    } else if (typeof binding.value === 'object') {
        // Object usage: v-show-on-intersect="{ type: 'fade-up', duration: '2s', transform: 'translateX(-100px)' }"
        options = { ...binding.value }
    }

    // Set defaults
    const {
        type = 'fade-up',
        duration = '1s',
        easing = 'cubic-bezier(0.4, 0, 0.2, 1)',
        delay = '0s',
        opacity = '0',
        transform,
        threshold = 0.1
    } = options

    el._options = options

    // Get initial transform (custom or preset)
    const initialTransform = transform || getInitialTransform(type)

    // Initially hide the element
    el.style.opacity = String(opacity)
    el.style.transform = initialTransform
    el.style.transition = `all ${duration} ${easing} ${delay}`

    const observer = new IntersectionObserver((entries) => {
        entries.forEach((entry) => {
            if (entry.isIntersecting) {
                // Show element
                el.style.opacity = '1'
                el.style.transform = 'none'
            } else {
                // Hide element
                el.style.opacity = String(opacity)
                el.style.transform = initialTransform
            }
        })
    }, {
        threshold: threshold as number
    })

    el._observer = observer
    observer.observe(el)
}

export const intersectionTransition: Directive = {
    mounted(el: IntersectionElement, binding) {
        setupTransition(el, binding)
    },

    updated(el: IntersectionElement, binding) {
        // Handle dynamic updates to the directive value
        if (JSON.stringify(binding.value) !== JSON.stringify(binding.oldValue)) {
            // Disconnect old observer and setup with new options
            if (el._observer) {
                el._observer.disconnect()
            }
            setupTransition(el, binding)
        }
    },

    unmounted(el: IntersectionElement) {
        if (el._observer) {
            el._observer.disconnect()
        }
    }
}

function getInitialTransform(transitionType: string): string {
    switch (transitionType) {
        case 'fade-up':
            return 'translateY(5em)'
        case 'fade-down':
            return 'translateY(-5em)'
        case 'slide-left':
            return 'translateX(5em)'
        case 'slide-right':
            return 'translateX(-5em)'
        case 'scale':
            return 'scale(0.8)'
        case 'scale-up':
            return 'scale(1.2)'
        case 'rotate':
            return 'rotate(180deg)'
        case 'rotate-left':
            return 'translateY(100px) rotate(12deg) scale(0.9)'
        case 'rotate-right':
            return 'translateY(100px) rotate(-12deg) scale(0.9)'
        case 'flip-x':
            return 'rotateX(90deg)'
        case 'flip-y':
            return 'rotateY(90deg)'
        default:
            return ''
    }
}
