import { debounce } from './tickers'

CUSTOM_EVENT_LISTENERS = []

/**
 * Check if element is Window
 * @param  {DOMElement} $el - Element to check
 * @return {boolean}    True if window
 */

const isWindow = $el => $el === window


/**
 * Check if element is a DOM element
 * @param  {DOMElement} $el - Element to check
 * @return {boolean}    True if dom element
 */

const isDomElement = $el => ($el instanceof Element || $el instanceof HTMLDocument || $el instanceof HTMLDocument)


/**
 * Check if element is Window or DOM element
 * @param  {Element}    $el - Element to check
 * @return {boolean}    True if window or DOM element
 */

const isValidElement = $el => (isWindow($el) || isDomElement($el))


/**
 * Check if element already has the event attached
 * @param  {Element}    $el     - Element where the event is attached
 * @param  {String}     event   - The event name
 * @return {Boolean}    True if the event is already attached to the element
 */

const getCustomEventIndex = ($el, event) => CUSTOM_EVENT_LISTENERS.findIndex(e => e.$el === $el && e.event === event)


/**
 * Check if element already has the event attached
 * @param  {Element}    $el     - Element where the event is attached
 * @param  {String}     event   - The event name
 * @return {Boolean}    True if the event is already attached to the element
 */

const customEventIsDefined = ($el, event) => getCustomEventIndex($el, event) > -1


/**
 * Add custom event to event storage
 * @param  {Element}    $el     - Element where the event is attached
 * @param  {String}     event   - The event name
 * @return {void}
 */

const addCustomEvent = ($el, event) => {
    if(!customEventIsDefined($el, event)) {
        CUSTOM_EVENT_LISTENERS.push({
            $el,
            event
        })
    }
}


/**
 * Remove custom event to event storage
 * @param  {Element}    $el     - Element where the event is attached
 * @param  {String}     event   - The event name
 * @return {void}
 */

const removeCustomEvent = ($el, event) => {
    const customEventIndex = getCustomEventIndex($el, event)
    if(customEventIndex > -1) {
        CUSTOM_EVENT_LISTENERS.splice(customEventIndex, 1)
    }
}


/**
 * Create a sarting event for the event triggered
 * @param  {Element}    $el     - Element to bind the event to
 * @param  {object}     event   - The triggered event's name
 * @return {void}
 */

const addStartEvent = ($el, event, delay = 200) => {

    // Check element
    if(!isValidElement($el)) {
        console.warn(`[addStartEvent:${event}]: Wrong parameter '${el}'. The parameter must be document, window or a DOM element`)
        return
    }

    const eventName = `${event}Start`

    // Check if event already exists
    if(customEventIsDefined($el, eventName)) {
        return
    }

    // Register element and event
    addCustomEvent($el, eventName)

    // Create event
    const startEvent = new CustomEvent(eventName)
    $el.addEventListener(event, debounce(() => {
        $el.dispatchEvent(startEvent)
    }, delay, true))
}

/**
 * Create an ending event for the event triggered
 * @param  {Element}    $el     - Element to bind the event to
 * @param  {object}     event   - The triggered event's name
 * @return {void}
 */

const addEndEvent = ($el, event, delay = 200) => {

    // Check element
    if(!isValidElement($el)) {
        console.warn(`[addEndEvent:${event}]: Wrong parameter '${el}'. The parameter must be document, window or a DOM element`)
        return
    }

    const eventName = `${event}End`

    // Check if event already exists
    if(customEventIsDefined($el, eventName)) {
        return
    }

    // Register element and event
    addCustomEvent($el, eventName)

    // Create event
    const endEvent = new CustomEvent(eventName)
    $el.addEventListener(event, debounce(() => {
        $el.dispatchEvent(endEvent)
    }, delay))
}


/**
 * Add scrollUp event to element (window by default)
 * @param  {Element} $el - Element to bind the event to
 * @return {void}
 */

const addScrollUpEvent = ($el = window) => {

    // Check element
    if(!isValidElement($el)) {
        console.warn(`[addScrollUpEvent]: Wrong parameter '${el}'. The parameter must be window or a DOM element`)
        return
    }

    let scrollTop = $el.scrollTop
    let previousScrollTop = scrollTop
    let direction = 0
    const scrollUp = new CustomEvent('scrollUp')
    const scrollProperty = isWindow($el) ? 'scrollY' : 'scrollTop'

    $el.addEventListener('scroll', e => {
        scrollTop = $el[scrollProperty]

        // Scroll up
        if(scrollTop < previousScrollTop && direction > -1) {
            $el.dispatchEvent(scrollUp)
            direction = -1

        // Scroll down
        } else if(scrollTop > previousScrollTop && direction < 1) {
            direction = 1
        }

        previousScrollTop = scrollTop
    })
}


/**
 * Add scrollDown event to element (window by default)
 * @param  {Element} $el - Element to bind the event to
 * @return {void}
 */

const addScrollDownEvent = ($el = window) => {

    // Check element
    if(!isValidElement($el)) {
        console.warn(`[addScrollDownEvent]: Wrong parameter '${el}'. The parameter must be window or a DOM element`)
        return
    }

    let scrollTop = $el.scrollTop
    let previousScrollTop = scrollTop
    let direction = 0
    const scrollDown = new CustomEvent('scrollDown')
    const scrollProperty = isWindow($el) ? 'scrollY' : 'scrollTop'

    $el.addEventListener('scroll', e => {
        scrollTop = $el[scrollProperty]

        // Scroll up
        if(scrollTop < previousScrollTop && direction > -1) {
            direction = -1

        // Scroll down
        } else if(scrollTop > previousScrollTop && direction < 1) {
            $el.dispatchEvent(scrollDown)
            direction = 1
        }

        previousScrollTop = scrollTop
    })
}

export {
    addStartEvent,
    addEndEvent,
    addScrollUpEvent,
    addScrollDownEvent,
    removeCustomEvent
}

@@ -966,20 +966,17 @@
 %0A%0Aconst 
-getC
+c
 ustomEve
@@ -978,20 +978,24 @@
 omEventI
-ndex
+sDefined
  = ($el,
@@ -1082,343 +1082,8 @@
 ent)
-%0A%0A%0A/**%0A * Check if element already has the event attached%0A * @param  %7BElement%7D    $el     - Element where the event is attached%0A * @param  %7BString%7D     event   - The event name%0A * @return %7BBoolean%7D    True if the event is already attached to the element%0A */%0A%0Aconst customEventIsDefined = ($el, event) =%3E getCustomEventIndex($el, event)
  %3E -
@@ -1452,400 +1452,8 @@
 %7D%0A%0A%0A
-/**%0A * Remove custom event to event storage%0A * @param  %7BElement%7D    $el     - Element where the event is attached%0A * @param  %7BString%7D     event   - The event name%0A * @return %7Bvoid%7D%0A */%0A%0Aconst removeCustomEvent = ($el, event) =%3E %7B%0A    const customEventIndex = getCustomEventIndex($el, event)%0A    if(customEventIndex %3E -1) %7B%0A        CUSTOM_EVENT_LISTENERS.splice(customEventIndex, 1)%0A    %7D%0A%7D%0A%0A%0A
 /**%0A
@@ -2023,32 +2023,116 @@
 , eventName)) %7B%0A
+        console.log(%60%5BaddStartEvent:$%7Bevent%7D%5D: Already exists for '$%7Bel%7D' element%60)%0A
         return%0A 
@@ -2957,32 +2957,114 @@
 , eventName)) %7B%0A
+        console.log(%60%5BaddEndEvent:$%7Bevent%7D%5D: Already exists for '$%7Bel%7D' element%60)%0A
         return%0A 
@@ -5403,28 +5403,6 @@
 nt,%0A
-    removeCustomEvent%0A
 %7D%0A

Remove removeCustomEvent (no use). Add logs