var icons = {
  loading: 'data:Image/gif;base64,[encoded data, 67208 characters]',
  leftArrow: 'data:Image/png;base64,[encoded data, 19704 characters]',
  
}

Element.prototype.createE = function(tag, referance, content) { 
    var element = document.createElement(tag);

    if (referance && referance[0] === '#'){
        element.id = referance.replace('#', '')
    } else if (referance) {
        element.classList = referance;
    }

    if (content && tag.toUpperCase() == 'IMG') {
        element.src = content;
    } else if (content) {
        element.innerHTML = content;
    }

    if (!this.doctype){ 
        var final = this.appendChild(element);
    }

    return final || element;
};

var loop, columns, delay; 

var loading = document.body.createE('div', 'container')
loading.style.background = "url(" + icons.loading + ") no-repeat center";
loading.style.backgroundSize = "125px";

var prev = document.body.createE('div', '#prev')

prev.setAttribute('onclick', 'nextPrev(-1)')

var next = document.body.createE('div', '#next')

next.setAttribute('onclick', 'nextPrev(1)')

var dots = document.body.createE('div', '#dots')

// Fetch movie data from get_movies.php
fetch('movies.php')
    .then(response => response.json())
    .then(data => {
        makeSlideshow(data);
    })
    .catch(error => {
        console.error('Error fetching movies:', error);
    });

function makeSlideshow(input, n = input.length) { 
    init(input)
    downloadImage(input, n)

    async function downloadImage(input) { 
        for (var i = 0; i < n; i++) {
            await new Promise((resolve, reject) => {
                var image = new Image();
                image.src = input[i].image;
                image.onload = () => {
                    createDot(input[i], i)
                    resolve()
                }
                image.onerror = () => {
                    createDot(input[i], i, true)
                    resolve()
                }
            })
        }
    }
}

function init(_input, _columns = 12, _delay = 7000) { 
    input = _input;
    columns = _columns;
    delay = _delay;
}

function createDot(slide, index, err) { 
    err ? slide.image = '404.png': null;
    var dotContainer = dots.createE('div', 'dot-container')

    var dot = dotContainer.createE('div', 'dot')
    dot.style.backgroundImage = "url(" + slide.artWork + ")";
    dot.setAttribute("onclick", "showSlide(" + index + ")")

    if (index == 0) { slideshow(slide) }
}

function slideshow(slide) { 
    var firstSlide = makeLayout(slide)
    visibleBox(firstSlide.boxes)
    document.getElementsByClassName('dot')[0].classList.add('active')

    loop = setTimeout(() => {
        nextPrev(1)    
    }, delay)
}

function showSlide(n) { 
    clearTimeout(loop);
    makeAnimation(input[n])
    var allDots = document.getElementsByClassName('dot');
    for (var i = 0; i < allDots.length; i++) {
        allDots[i].classList.remove('active');
    }
    var dot = allDots[n]
    dot.classList.add('active')
    loop = setTimeout(() => {
        nextPrev(1)
    }, delay)
}

function nextPrev(n) {
	clearTimeout(loop);
	var allDots = document.getElementsByClassName('dot');
	for (var i = 0; i < allDots.length; i++) {
		var target = n + i;
		if (allDots[i].classList.contains('active')) {
			allDots[i].classList.remove('active')
			if (target >= allDots.length) { target = 0 }
			else if (target < 0) { target = allDots.length - 1 }
			makeAnimation(input[target])
			allDots[target].classList.add('active')
			break;
		}
	}
	loop = setTimeout(() => {
		nextPrev(1)
	}, delay)
}

function makeAnimation(slide) {
	removePrevious();
	var animation = [
		'pushUpDown(slide)',
		'pullUpDown(slide)',
		'pullDown(slide)',
		'pullUp(slide)',
		'boxEmerge(slide)',
		'boxEmergeReverse(slide)',
		'pushUp(slide)',
		'pushDown(slide)',
		'fade(slide)',
		'slideCol(slide)',
		'slideColReverse(slide)',
		'slideIn(slide, "Left")',
		'slideIn(slide, "Right")',
		'slideIn(slide, "Up")',
		'slideIn(slide, "Down")',
		'slideOut(slide, "Left")',
		'slideOut(slide, "Right")',
		'slideOut(slide, "Up")',
		'slideOut(slide, "Down")',
		'slideWith(slide, "Left")',
		'slideWith(slide, "Right")',
		'slideWith(slide, "Up")',
		'slideWith(slide, "Down")',
	]

	var x = Math.floor(Math.random() * animation.length)
	eval(animation[x])
}

function makeLayout(slide, out) {  
	var oldContainer = document.getElementsByClassName('container')
	oldContainer = oldContainer[oldContainer.length - 1]
	
	
	if (out) {
		var oldVertical = oldContainer.getElementsByClassName('col')
		var oldBoxes = [];
		for (var i = 0; i < oldVertical.length; i++) {
			oldVertical[i].className = 'col';
			var oldRows = oldVertical[i].getElementsByClassName('row')
			var oldOneCol = [];
			for (var j = 0; j < oldRows.length; j++) {
				var content = oldRows[j].getElementsByClassName('content')[0];
				content.className = 'content visible';
				oldOneCol.push(content);
			}
			oldBoxes.push(oldOneCol)
		}
		oldContainer.style.zIndex = 1;
	}

	var container = document.body.createE('div', 'container')
	var boxes = [];
	var vertical = [];

	for (var i = 0; i < columns; i++) {
		vertical.push(container.createE('div', 'col'))
	}

	
	var rows = Math.floor(window.innerHeight / vertical[0].offsetWidth);

	for (var i = 0; i < vertical.length; i++) {
		var horizontal = [];
		for (var j = 0; j < rows; j++) {
			horizontal.push(vertical[i].createE('div', 'row'))
		}
		var oneCol = [];
		for (var j = 0; j < horizontal.length; j++) {
			oneCol.push(horizontal[j].createE('div', 'content'))
		}
		boxes.push(oneCol)
		createBackground(oneCol, slide.image)
	}

	function createBackground(slices, image) { 
		for (var i = 0; i < slices.length; i++) {
			slices[i].style.backgroundImage = "url(" + image + ")";
			positionBackground(slices[i])
		}
	}

	createSlideHeader(slide.artWork, slide.title, slide.subtitle, slide.url)

	
	out ? visibleBox(boxes) : null

	return {
		vertical: oldVertical || vertical,
		boxes: oldBoxes || boxes,
		container: container,
		oldContainer: oldContainer
	}
}

function positionBackground(slice) {
	slice.style.backgroundPosition = -(slice.offsetLeft) + "px " + -(slice.offsetTop) + "px";
	slice.style.backgroundSize = window.innerWidth + "px";
}

function visibleBox(boxes) { 
	
	if (boxes[0][0]) {
		for (var i = 0; i < boxes.length; i++) {
			for (var j = 0; j < boxes[i].length; j++) {
				boxes[i][j].classList.add('visible')
			}
		}
	} else {
		for (var i = 0; i < boxes.length; i++) {
			boxes[i].classList.add('visible')
		}
	}

}

function removePrevious() { 
	var containers = document.getElementsByClassName('container')
	if (containers.length >= 2) {containers[0].remove()}

	var slideHeader = document.querySelectorAll('.slide-header');
	if (slideHeader.length >= 2) {
		for (var i = 0; i < slideHeader.length; i++) {
			slideHeader[i].remove();
		}
	} else if (slideHeader.length >= 1) {
		slideHeader[0].classList.add('out')
		slideHeader[0].classList.remove('in');
		setTimeout(() => {
			slideHeader[0].remove();
		}, 500)
	}
}

async function timeline(boxes, className, colDelay, rowDelay) {
	colsAwait(boxes)
	async function colsAwait(boxes) {
		for (var i = 0; i < boxes.length; i++) {
			colDelay ? await new Promise(resolve => setTimeout(resolve, colDelay)) : null
			boxesAwait(boxes[i])
		}
	}
	async function boxesAwait(boxes) {
		for (var i = 0; i < boxes.length; i++) {
			rowDelay ? await new Promise(resolve => setTimeout(resolve, rowDelay)) : null
			boxes[i].classList.add(className)
		}
	}
}

Array.prototype.boxReverse = function() {
	this.reverse()
	for (var i = 0; i < this.length; i++) {
		this[i].reverse()
	}
	return this
}

window.addEventListener('resize', () => {
	var slices = document.querySelectorAll('.content');
	for (var i = slices.length - 1; i >= 0; i--) {
		positionBackground(slices[i])
	}
})

function createSlideHeader(artwork, title, subtitle, url) {
    var slideHeader = document.body.createE('div', 'slide-header');
    var headerText = slideHeader.createE('div', 'header-text');
    var titleElement = headerText.createE('h3', null, title);
    var subtitleElement = headerText.createE('p', null, subtitle);

    // The grand entrance of the artwork image at the end
    var artworkImage = slideHeader.createE('img', null, artwork);

    slideHeader.classList.add('in');
}


async function pushUpDown(input) {
	var layout = makeLayout(input)
	var cols = layout.vertical
	for (var i = 0; i < cols.length; i++) {
		await new Promise(resolve => setTimeout(resolve, 50))
		visibleBox(layout.boxes[i])
		cols[i].classList.add('pushUpDown')
	}
}

async function pullUpDown(input) {
	var layout = makeLayout(input, true)
	var cols = layout.vertical
	for (var i = 0; i < cols.length; i++) {
		await new Promise(resolve => setTimeout(resolve, 50))
		visibleBox(layout.boxes[i])
		cols[i].classList.add('pullUpDown')
	}
}

async function pullDown(input) { 
	var layout = makeLayout(input, true)
	var cols = layout.vertical
	for (var i = 0; i < cols.length; i++) {
		await new Promise(resolve => setTimeout(resolve, 75))
		cols[i].classList.add('pullDown')
	}
}

async function pullUp(input) { 
	var layout = makeLayout(input, true)
	var cols = layout.vertical
	for (var i = 0; i < cols.length; i++) {
		await new Promise(resolve => setTimeout(resolve, 75))
		cols[i].classList.add('pullUp')
	}
}

async function boxShrink(input) {
	var layout = makeLayout(input, true)
	var boxes = layout.boxes
	timeline(boxes, 'boxShrink', 75, 75)
}

async function boxShrinkReverse(input) {
	var layout = makeLayout(input, true)
	var boxes = layout.boxes
	boxes.boxReverse()

	timeline(boxes, 'boxShrink', 75, 75)
}

async function boxEmerge(input) {
	var layout = makeLayout(input)
	var boxes = layout.boxes

	timeline(boxes, 'boxEmerge', 75, 75)

}

async function boxEmergeReverse(input) {
	var layout = makeLayout(input)
	var boxes = layout.boxes
	boxes.boxReverse()

	timeline(boxes, 'boxEmerge', 75, 75)

}

async function slideCol(input) {
	var layout = makeLayout(input)
	var boxes = layout.boxes;
	timeline(boxes, 'slideCol', 75)
}

async function slideColReverse(input) {
	var layout = makeLayout(input)
	var boxes = layout.boxes;
	boxes.reverse()
	timeline(boxes, 'slideCol', 75)
}

async function pushUp(input) {
	var layout = makeLayout(input)
	var cols = layout.vertical
	for (var i = 0; i < cols.length; i++) {
		await new Promise(resolve => setTimeout(resolve, 75))
		visibleBox(layout.boxes[i])
		cols[i].classList.add('pushUp')
	}
}

async function pushDown(input) {
	var layout = makeLayout(input)
	var cols = layout.vertical
	for (var i = 0; i < cols.length; i++) {
		await new Promise(resolve => setTimeout(resolve, 75))
		visibleBox(layout.boxes[i])
		cols[i].classList.add('pushDown')
	}
}

function fade(input) {
	var layout = makeLayout(input)
	var boxes = layout.boxes;
	visibleBox(boxes)
	var container = layout.container;
	container.classList.add('fade')
}

function slideIn(input, direction) {
	var layout = makeLayout(input)
	var boxes = layout.boxes;
	visibleBox(boxes)
	var container = layout.container;
	var oldContainer = layout.oldContainer;
	container.className = 'container ' + 'push' + direction;
	oldContainer.className = 'container smaller';
}

function slideOut(input, direction) {
	var layout = makeLayout(input, true)
	var container = layout.container;
	var oldContainer = layout.oldContainer;
	oldContainer.className = 'container ' + 'pull' + direction;
	container.className = 'container bigger';
}

function slideWith(input, direction) {
	var layout = makeLayout(input, true);
	var container = layout.container;
	var oldContainer = layout.oldContainer;
	oldContainer.className = 'container ' + 'pull' + direction;
	container.className = 'container ' + 'push' + direction;
}