<template>
	<div class="tooltip-container">
		<div
			ref="trigger"
			class="trigger noselect"
			@click.stop="toggle"
		>
			<slot />
		</div>

		<teleport to="body">
			<div
				v-if="opened"
				ref="tooltip"
				class="tooltip-wrapper"
				:style="{ transform: `translate3d(${tooltipX}px, ${tooltipY}px, 0)` }"
			>
				<div class="tooltip-inner">
					<div class="tooltip">
						<slot name="tooltip" />
					</div>
				</div>
			</div>
		</teleport>
	</div>
</template>

<script>
import { nextTick } from 'vue';

function getX(triggerBoundary, tooltipBoundary) {
	const idealPosition = triggerBoundary.left + (triggerBoundary.width / 2) - (tooltipBoundary.width / 2);

	// don't overflow left edge
	if (idealPosition < 0) {
		return 0;
	}

	// don't overflow right edge
	if (idealPosition + tooltipBoundary.width > window.innerWidth) {
		return window.innerWidth - tooltipBoundary.width;
	}

	// position at the center of trigger
	return idealPosition;
}

async function calculate() {
	if (!this.opened) {
		return;
	}

	const triggerBoundary = this.$refs.trigger.getBoundingClientRect();
	const tooltipBoundary = this.$refs.tooltip.getBoundingClientRect();

	this.tooltipY = triggerBoundary.top + triggerBoundary.height;
	this.tooltipX = this.getX(triggerBoundary, tooltipBoundary);
}

async function open() {
	this.events.emit('blur');

	await nextTick();

	this.opened = true;
	await nextTick();

	this.calculate();
}

function close() {
	this.opened = false;

	this.tooltipY = 0;
	this.tooltipX = 0;
}

function toggle() {
	if (this.opened) {
		this.close();
		return;
	}

	this.open();
}

function mounted() {
	this.events.on('blur', () => {
		this.close();
	});

	this.events.on('resize', () => {
		this.calculate();
	});
}

export default {
	data() {
		return {
			opened: false,
			tooltipX: 0,
			tooltipY: 0,
		};
	},
	mounted,
	methods: {
		calculate,
		getX,
		open,
		close,
		toggle,
	},
};
</script>

<style lang="scss" scoped>
.tooltip-wrapper {
	display: flex;
	top: 0;
	left: 0;
	flex-direction: column;
	justify-content: center;
	position: absolute;
	z-index: 10;
}

.tooltip-inner {
	position: relative;
	box-shadow: 0 0 3px var(--darken-weak);

	&:after {
		content: '';
		width: 0;
		height: 0;
		position: absolute;
		top: -.5rem;
		left: calc(50% - .5rem);
		border-left: .5rem solid transparent;
		border-right: .5rem solid transparent;
		border-bottom: .5rem solid var(--background-light);
		margin: 0 auto;
		filter: drop-shadow(0 0 3px var(--darken-weak));
	}
}

.tooltip {
	position: relative;
	background: var(--background-light);
}
</style>