<script lang="ts">
import {defineComponent, PropType} from 'vue';
import Tile from './Tile.vue';
import {LayoutNode} from '../layout';
import type {LayoutOptions} from '../layout';

export default defineComponent({
	props: {
		layoutNode: {type: Object as PropType<LayoutNode>, required: true},
		lytOpts: {type: Object as PropType<LayoutOptions>, required: true},
		uiOpts: {type: Object, required: true},
		nonAbsPos: {type: Boolean, default: false},
		highlight: {type: Boolean, default: false},
		inTransition: {type: Boolean, default: false},
	},
	computed: {
		showHeader(){
			return (this.layoutNode.showHeader && !this.layoutNode.sepSweptArea) ||
				(this.layoutNode.sepSweptArea && this.layoutNode.sepSweptArea.sweptLeft);
		},
		nonLeafBgColor(){
			let colorArray = this.uiOpts.nonLeafBgColors;
			return colorArray[this.layoutNode.depth % colorArray.length];
		},
		styles(): Record<string,string> {
			let placementStyles;
			if (!this.layoutNode.hidden){
				placementStyles = {
					position: 'absolute',
					left: this.layoutNode.pos[0] + 'px',
					top: this.layoutNode.pos[1] + 'px',
					width: this.layoutNode.dims[0] + 'px',
					height: this.layoutNode.dims[1] + 'px',
					visibility: 'visible',
				};
			} else {
				placementStyles = {
					position: 'absolute',
					left: '0',
					top: '0',
					width: '0',
					height: '0',
					visibility: 'hidden',
				};
			}
			let borderR = this.uiOpts.borderRadius + 'px';
			if (this.layoutNode.sepSweptArea != null){
				borderR = this.layoutNode.sepSweptArea.sweptLeft ?
					`${borderR} ${borderR} ${borderR} 0` :
					`${borderR} 0 ${borderR} ${borderR}`;
			}
			return {
				...placementStyles,
				// Transition related
				transitionDuration: this.uiOpts.transitionDuration + 'ms',
				transitionProperty: 'left, top, width, height, visibility',
				transitionTimingFunction: 'ease-out',
				zIndex: this.inTransition ? '1' : '0',
				overflow: this.inTransition ? 'hidden' : 'visible',
				// CSS variables
				'--nonLeafBgColor': this.nonLeafBgColor,
				'--tileSpacing': this.lytOpts.tileSpacing + 'px',
				// Other
				borderRadius: borderR,
				backgroundColor: this.nonLeafBgColor,
				boxShadow: this.inTransition ? 'none' :
					(this.highlight ? this.uiOpts.shadowHighlight :
						(this.layoutNode.hasFocus ? this.uiOpts.shadowFocused : this.uiOpts.shadowNormal)),
			};
		},
		headerStyles(): Record<string,string> {
			let borderR = this.uiOpts.borderRadius + 'px';
			return {
				height: this.lytOpts.headerSz + 'px',
				lineHeight: this.lytOpts.headerSz + 'px',
				fontSize: this.uiOpts.nonLeafHeaderFontSz + 'px',
				textAlign: 'center',
				color: this.uiOpts.nonLeafHeaderColor,
				backgroundColor: this.uiOpts.nonLeafHeaderBgColor,
				borderRadius: `${borderR} ${borderR} 0 0`,
				// For ellipsis
				overflow: 'hidden',
				textOverflow: 'ellipsis',
				whiteSpace: 'nowrap',
			};
		},
		sepSweptAreaStyles(): Record<string,string> {
			let commonStyles = {
				position: 'absolute',
				backgroundColor: this.nonLeafBgColor,
				boxShadow: this.inTransition ? 'none' :
					(this.highlight ? this.uiOpts.shadowHighlight :
						(this.layoutNode.hasFocus ? this.uiOpts.shadowFocused : this.uiOpts.shadowNormal)),
				transitionDuration: this.uiOpts.transitionDuration + 'ms',
				transitionProperty: 'left, top, width, height',
				transitionTimingFunction: 'ease-out',
			};
			let area = this.layoutNode.sepSweptArea;
			if (this.layoutNode.hidden || area == null){
				return {
					...commonStyles,
					visibility: 'hidden',
					left: '0',
					top: this.lytOpts.headerSz + 'px',
					width: '0',
					height: '0',
				};
			} else {
				let borderR = this.uiOpts.borderRadius + 'px';
				return {
					...commonStyles,
					left: area.pos[0] + 'px',
					top: area.pos[1] + 'px',
					width: area.dims[0] + 'px',
					height: area.dims[1] + 'px',
					borderRadius: area.sweptLeft ?
						`${borderR} 0 0 ${borderR}` :
						`${borderR} ${borderR} 0 0`,
				};
			}
		},
	},
	methods: {
		onMouseEnter(){
			this.$emit('tile-mouse-enter');
		},
		onMouseLeave(){
			this.$emit('tile-mouse-leave');
		},
		onMouseDown(){
			this.$emit('tile-mouse-down');
		},
		onMouseUp(){
			this.$emit('tile-mouse-up');
		},
		// Child event propagation
		onInnerLeafClicked(data: LayoutNode){
			this.$emit('leaf-clicked', data);
		},
		onInnerHeaderClicked(data: LayoutNode){
			this.$emit('header-clicked', data);
		},
		onInnerLeafClickHeld(data: LayoutNode){
			this.$emit('leaf-click-held', data);
		},
		onInnerHeaderClickHeld(data: LayoutNode){
			this.$emit('header-click-held', data);
		},
		onInnerInfoIconClicked(data: LayoutNode){
			this.$emit('info-icon-clicked', data);
		},
	},
	name: 'non-leaf-tile', // Need this to use self in template
	emits: [
		'leaf-clicked', 'header-clicked', 'leaf-click-held', 'header-click-held', 'info-icon-clicked',
		'tile-mouse-enter', 'tile-mouse-leave', 'tile-mouse-down', 'tile-mouse-up',
	],
	components: {Tile, },
});
</script>

<template>
<div :style="styles">
	<h1 v-if="showHeader" :style="headerStyles" class="hover:cursor-pointer"
		@mouseenter="onMouseEnter" @mouseleave="onMouseLeave"
		@mousedown="onMouseDown" @mouseup="onMouseUp">
		{{layoutNode.tolNode.name}}
	</h1>
	<div :style="sepSweptAreaStyles"
		:class="layoutNode?.sepSweptArea?.sweptLeft ? 'hide-right-edge' : 'hide-top-edge'">
		<h1 v-if="layoutNode?.sepSweptArea?.sweptLeft === false"
			:style="headerStyles" class="hover:cursor-pointer"
			@mouseenter="onMouseEnter" @mouseleave="onMouseLeave"
			@mousedown="onMouseDown" @mouseup="onMouseUp">
			{{layoutNode.tolNode.name}}
		</h1>
	</div>
	<tile v-for="child in layoutNode.children" :key="child.tolNode.name"
		:layoutNode="child" :lytOpts="lytOpts" :uiOpts="uiOpts"
		@leaf-clicked="onInnerLeafClicked" @header-clicked="onInnerHeaderClicked"
		@leaf-click-held="onInnerLeafClickHeld" @header-click-held="onInnerHeaderClickHeld"
		@info-icon-clicked="onInnerInfoIconClicked"/>
</div>
</template>

<style>
.hide-right-edge::before {
	content: '';
	position: absolute;
	background-color: var(--nonLeafBgColor);
	right: calc(0px - var(--tileSpacing));
	bottom: 0;
	width: var(--tileSpacing);
	height: calc(100% + var(--tileSpacing));
}
.hide-top-edge::before {
	content: '';
	position: absolute;
	background-color: var(--nonLeafBgColor);
	bottom: calc(0px - var(--tileSpacing));
	right: 0;
	width: calc(100% + var(--tileSpacing));
	height: var(--tileSpacing);
}
</style>
