/**
 * image-gallery.js
 *
 *
 */
import PhotoSwipe from 'photoswipe/dist/photoswipe'
import PhotoSwipeUI_Default from 'photoswipe/dist/photoswipe-ui-default';
import ElementHelpers from '../helpers/element-helpers';

/**
 * Declare constants
 */
const attributeBase = 'data-rs-image-gallery';

export class ImageGallery {

	constructor(element) {
		this.element = element;
		this.initPhotoSwipeFromDOM(this.classes.gallerySelector);

	}

	/**
	 * Declare attribute constants
	 */
	get attributes() {
		return {
			imageSize: `${attributeBase}-image-size`,
			totalsOverlay: `${attributeBase}-totals-overlay`,
			totalPhotos: `${attributeBase}-total-photos`,
			photoSwipeUid: 'data-pswp-uid'
		}
	}

	/**
	 * Declare classes
	 */
	get classes() {
		return {
			gallerySelector: '.image-gallery-selector',
			photoTotalsOverlay: 'photo-totals-overlay',
			photoswipeElement: '.pswp',
			hidden: 'hidden'
		}
	}


	initPhotoSwipeFromDOM(gallerySelector) {
		// loop through all gallery elements and bind events
		const galleryElements = document.querySelectorAll(gallerySelector);

		galleryElements.forEach((item, index) => {
			item.setAttribute(this.attributes.photoSwipeUid, index + 1);
			item.onclick = this.onThumbnailsClick.bind(this);

			let figureArray = [...item.childNodes];
			const figureElements = figureArray.filter(element => {
				return element.nodeName === 'FIGURE';
			});

			let count = 0;
			figureElements.forEach((element, index) => {
				if (index === 2) {
					element.setAttribute(this.attributes.totalsOverlay, true)
				} else if (index > 2) {
					element.classList.add(this.classes.hidden);
				}
				count++;
			});
			this.thirdPhoto = ElementHelpers.getElementByAttributeWithinElement(this.element, this.attributes.totalsOverlay, true);
			this.thirdPhoto.setAttribute(this.attributes.totalPhotos, count);
			this.setTotalsOverlay();
		});


		// Parse URL and open gallery if it contains #&pid=3&gid=1
		const hashData = this.photoswipeParseHash();
		if (hashData.pid && hashData.gid) {
			this.openPhotoSwipe(hashData.pid, galleryElements[hashData.gid - 1], true, true);
		}
	}

	setTotalsOverlay() {
		const totalPhotoTextBefore = this.element.dataset.rsImageGalleryTotalPhotoTextBefore || ' ';
		const totalPhotoTextAfter = this.element.dataset.rsImageGalleryTotalPhotoTextAfter || ' ';
		const photoAmount = this.thirdPhoto.dataset.rsImageGalleryTotalPhotos || '';
		this.thirdPhoto.insertAdjacentHTML('beforeend', `<div class=${this.classes.photoTotalsOverlay}>${totalPhotoTextBefore} ${photoAmount} ${totalPhotoTextAfter}</div>`);
	}


	// triggers when user clicks on thumbnail
	onThumbnailsClick(event) {
		event.preventDefault ? event.preventDefault() : event.returnValue = false;

		const eTarget = event.target;

		// find nearest parent element
		const closest = function closest(element, fn) {
			return element && (fn(element) ? element : closest(element.parentNode, fn));
		};

		// find root element of slide
		const clickedListItem = closest(eTarget, function (element) {
			return (element.tagName && element.tagName.toUpperCase() === 'FIGURE');
		});

		if (!clickedListItem) {
			return;
		}

		// find index of clicked item by looping through all child nodes
		let clickedGallery = clickedListItem.parentNode,
			childNodes = clickedListItem.parentNode.childNodes,
			numChildNodes = childNodes.length,
			nodeIndex = 0,
			index;

		for (let i = 0; i < numChildNodes; i++) {
			if (childNodes[i].nodeType !== 1) {
				continue;
			}

			if (childNodes[i] === clickedListItem) {
				index = nodeIndex;
				break;
			}
			nodeIndex++;
		}


		if (index >= 0) {
			// open PhotoSwipe if valid index found
			this.openPhotoSwipe(index, clickedGallery, true, false)
		}
		return false;
	}


	// parse picture index and gallery index from URL (#&pid=1&gid=2)
	photoswipeParseHash() {
		const hash = window.location.hash.substring(1),
			params = {};

		if (hash.length < 5) {
			return params;
		}

		const vars = hash.split('&');
		for (let i = 0; i < vars.length; i++) {
			if (!vars[i]) {
				continue;
			}
			const pair = vars[i].split('=');
			if (pair.length < 2) {
				continue;
			}
			params[pair[0]] = pair[1];
		}

		if (params.gid) {
			params.gid = parseInt(params.gid, 10);
		}

		return params;
	}

	openPhotoSwipe(index, galleryElement, disableAnimation, fromURL) {
		let pswpElement = document.querySelectorAll(this.classes.photoswipeElement)[0],
			gallery,
			options,
			items;

		items = this.parseThumbnailElements(galleryElement);

		// define options (if needed)
		options = {
			// define gallery index (for URL)
			galleryUID: galleryElement.getAttribute(this.attributes.photoSwipeUid),
			showAnimationDuration: 300,
			showHideOpacity: true,
			spacing: 0.5
		};

		// PhotoSwipe opened from URL
		if (fromURL) {
			if (options.galleryPIDs) {
				// parse real index when custom PIDs are used
				// http://photoswipe.com/documentation/faq.html#custom-pid-in-url
				for (let j = 0; j < items.length; j++) {
					if (items[j].pid === index) {
						options.index = j;
						break;
					}
				}
			} else {
				// in URL indexes start from 1
				options.index = parseInt(index, 10) - 1;
			}
		} else {
			options.index = parseInt(index, 10);
		}

		// exit if index not found
		if (isNaN(options.index)) {
			return;
		}

		if (disableAnimation) {
			options.showAnimationDuration = 0;
		}

		// Pass data to PhotoSwipe and initialize it
		gallery = new PhotoSwipe(pswpElement, PhotoSwipeUI_Default, items, options);
		gallery.init();
	}

	// parse slide data (url, title, size ...) from DOM elements
	// (children of gallerySelector)
	parseThumbnailElements(el) {
		let thumbElements = el.childNodes,
			numNodes = thumbElements.length,
			items = [],
			figureEl,
			linkEl,
			size,
			item;

		for (let i = 0; i < numNodes; i++) {

			figureEl = thumbElements[i]; // <figure> element

			// include only element nodes
			if (figureEl.nodeType !== 1) {
				continue;
			}

			linkEl = figureEl.children[0]; // <a> element

			size = linkEl.getAttribute(this.attributes.imageSize).split('x');

			// create slide object
			item = {
				src: linkEl.getAttribute('href'),
				w: parseInt(size[0], 10),
				h: parseInt(size[1], 10)
			};


			if (linkEl.children.length > 0) {
				// <img> thumbnail element, retrieving thumbnail url
				item.msrc = linkEl.children[0].getAttribute('src');
			}

			item.el = figureEl; // save link to element for getThumbBoundsFn
			items.push(item);
		}

		return items;
	}

	/**
	 * Get selector
	 */
	static getSelector() {
		return `[${attributeBase}]`;
	}
}
