export class PopupWrapper {
	/**
	 * Returns the Popup class.
	 *
	 * Unfortunately, the Popup class can only be defined after
	 * google.maps.OverlayView is defined, when the Maps API is loaded.
	 */
	static get popupClass() {

		/**
		 * A customized popup on the map.
		 * @param {!google.maps.LatLng} position
		 * @param {!Element} content The bubble div.
		 * @constructor
		 */
		function Popup(position, content, marker) {
			this.position = position;
			this.content = content;
			this.marker = marker;
			this.content.classList.add('popup-bubble');
			// This zero-height div is positioned at the bottom of the tip.
			this.containerDiv = document.createElement('div');
			this.containerDiv.classList.add('popup-bubble__container');
			this.containerDiv.appendChild(content);

			// Optionally stop clicks, etc., from bubbling up to the map.
			google.maps.OverlayView.preventMapHitsAndGesturesFrom(this.containerDiv);
		}

		// extend google.maps.OverlayView.
		Popup.prototype = Object.create(google.maps.OverlayView.prototype);

		/** Called when the popup is added to the map. */
		Popup.prototype.onAdd = function () {
			this.getPanes().floatPane.appendChild(this.containerDiv);
			this.show();
		};

		/** Called when the popup is removed from the map. */
		Popup.prototype.onRemove = function () {
			if (this.containerDiv.parentElement) {
				this.containerDiv.parentElement.removeChild(this.containerDiv);
			}
		};

		/** Called each frame when the popup needs to draw itself. */
		Popup.prototype.draw = function () {
			const divPosition = this.getProjection().fromLatLngToDivPixel(this.position);

			// Hide the popup when it is far out of view.
			const display = Math.abs(divPosition.x) < 4000 && Math.abs(divPosition.y) < 4000 ?
				'block' :
				'none';
			if (display === 'block') {
				this.containerDiv.style.left = divPosition.x + 'px';
				this.containerDiv.style.top = divPosition.y + 'px';
			}

			if (this.containerDiv.style.display !== display) {
				this.containerDiv.style.display = display;
			}
		};

		Popup.prototype.height = function () {
			return getComputedStyle(this.content).getPropertyValue('height');
		}

		Popup.prototype.hide = function () {
			this.content.addEventListener('transitionend', () => {
				let opacity = getComputedStyle(this.content).getPropertyValue('opacity');
				if (opacity <= 0.1) {
					this.setMap(null);
				}
			});

			this.content.classList.remove('active');
		}

		Popup.prototype.show = function () {
			setTimeout(() => {
				this.content.classList.add('active');
				setTimeout(() => {
					let popupHeight = parseInt(getComputedStyle(this.content).getPropertyValue('height'));
					if (!isNaN(popupHeight)) {
						let offsetY = -1 * ((popupHeight / 2) + this.marker.icon.size.height);
						this.marker.map.panToWithOffset(this.marker.getPosition(), 0, offsetY);
					}
				});
			},50);
		}

		return Popup;
	}
}
