import { throttle, debounce } from 'throttle-debounce'

/**
 *  Tiny Masonry
 *
 *  @author Björn Hase
 *  @license http://opensource.org/licenses/MIT The MIT License
 *  @link https://gitea.node001.net/tiny-components/masonry
 *
 */

class Masonry {

    /**
     *
     *
     */
    constructor(container, elements) {

        this.height = 0

        // getting elements 
        this.elements = elements
        this.container = container

        // getting gap for calculate from grid 
        this.gap = parseInt(getComputedStyle(this.container, 'gap').getPropertyValue('grid-gap').split(' ')[0])

        // adding loaded event 
        this.elements.forEach((element) => {
            const img = element.querySelector('img')

            if (img) {
                if (img.completed) {
                    this.calculate()
                } else {
                    img.addEventListener('load', () => {
                        this.calculate()
                    })
                }
            }
        })

        window.addEventListener('resize', throttle(300, () => {
            this.calculate()
        }), false)

        window.addEventListener('scroll', throttle(300, () => {
            this.calculate(true)
        }), false)

        this.calculate()
    }

    /**
     *
     *
     */
    calculate(onlyVisible = false) {

        // getting number of columns 
        if (!onlyVisible) {
            this.columns = Math.ceil(this.container.offsetWidth / this.elements[0].parentElement.offsetWidth) - 1

            if (this.columns === 0) {
                this.columns = 1
            }
        }

        this.height = []

        for (let i = 0; i < this.elements.length; i++) {

            let marginTop = 0

            // getting row 
            let row = Math.round(i / this.columns) + 1

            // reset margin-top for the first columns 
            if (i < this.columns) {
                this.elements[i].parentElement.dataset.offsetMarginTop = 0
            }

            // check for parent element and getting marginTop
            if (this.elements[i - this.columns] && !onlyVisible) {
                if (this.elements[i - this.columns].parentElement.dataset.offsetMarginTop) {
                    marginTop += parseInt(this.elements[i - this.columns].parentElement.dataset.offsetMarginTop)
                }

                marginTop += this.elements[i - this.columns].offsetHeight
            } else {
                marginTop = this.elements[i].parentElement.dataset.offsetMarginTop
            }

            if (!onlyVisible) {
                this.elements[i].parentElement.dataset.offsetMarginTop = marginTop
            }

            if (window.pageYOffset <= (marginTop + this.elements[i].offsetHeight + (this.gap * row)) && (window.pageYOffset + window.innerHeight + (this.gap * row)) >= marginTop) {
                this.elements[i].parentElement.style.marginTop = marginTop + 'px'
                this.elements[i].parentElement.style.visibility = 'visible'
            } else {
                this.elements[i].parentElement.style.visibility = 'hidden'
            }

            // add complete height for element
            this.height.push(parseInt(marginTop) + parseInt(this.elements[i].offsetHeight) + (this.gap * row))
        }

        // getting heighest height
        this.height = Math.max(...this.height)
        
        if (this.height > 0) { 
            this.container.style.height = this.height + 'px'
        }
    }
}

export default Masonry
