<script lang="ts" setup>
import { useCanvasNodeHandle } from '../../../../composables/useCanvasNodeHandle';
import { useCanvasNode } from '../../../../composables/useCanvasNode';
import { computed, ref, useCssModule } from 'vue';
import { useI18n } from '@n8n/i18n';
import CanvasHandleDot from './parts/CanvasHandleDot.vue';
import CanvasHandlePlus from './parts/CanvasHandlePlus.vue';
import { useCanvas } from '../../../../composables/useCanvas';
import { useZoomAdjustedValues } from '../../../../composables/useZoomAdjustedValues';
import { getMaxNodePortsLabelSize } from '../../../../canvas.utils';
import { injectCanvasRenderData } from '@/features/workflows/canvas/canvas.utils';

const emit = defineEmits<{
	add: [];
}>();

const $style = useCssModule();

const i18n = useI18n();
const { id } = useCanvasNode();
const renderData = injectCanvasRenderData();
const outputs = computed(() => renderData.value.nodeOutputsByNodeId.get(id.value)?.value ?? []);
const { label, isConnected, isConnecting, isReadOnly, isRequired, runData } = useCanvasNodeHandle();
const { viewport } = useCanvas();
const { calculateHandleLightness } = useZoomAdjustedValues(viewport);

const handleClasses = 'source';

const classes = computed(() => ({
	'canvas-node-handle-main-output': true,
	[$style.handle]: true,
	[$style.connected]: isConnected.value,
	[$style.required]: isRequired.value,
}));

const isHovered = ref(false);

const runDataTotal = computed(() => runData.value?.total ?? 0);

const runDataLabel = computed(() =>
	!isConnected.value && runData.value && runData.value.total > 0
		? i18n.baseText('ndv.output.items', {
				adjustToNumber: runData.value.total,
				interpolate: { count: String(runData.value.total) },
			})
		: '',
);

const isHandlePlusVisible = computed(() => !isConnecting.value || isHovered.value);

const plusType = computed(() => (runDataTotal.value > 0 ? 'success' : 'default'));

const plusLineSize = computed(() => {
	if (runDataTotal.value > 0) return 80;
	return { small: 46, medium: 66, large: 80 }[getMaxNodePortsLabelSize(outputs.value)];
});

const outputLabelClasses = computed(() => ({
	[$style.label]: true,
	[$style.outputLabel]: true,
}));

const runDataLabelClasses = computed(() => ({
	[$style.label]: true,
	[$style.runDataLabel]: true,
}));

const handleLightness = calculateHandleLightness();

const handleStyles = computed(() => ({
	'--handle--border--lightness--light': handleLightness.value.light,
	'--handle--border--lightness--dark': handleLightness.value.dark,
}));

function onMouseEnter() {
	isHovered.value = true;
}

function onMouseLeave() {
	isHovered.value = false;
}

function onClickAdd() {
	emit('add');
}
</script>
<template>
	<div :class="classes">
		<div v-if="label" :class="outputLabelClasses">{{ label }}</div>
		<div v-if="runData" :class="runDataLabelClasses">{{ runDataLabel }}</div>
		<CanvasHandleDot :handle-classes="handleClasses" :style="handleStyles" />
		<Transition name="canvas-node-handle-main-output">
			<CanvasHandlePlus
				v-if="!isConnected && !isReadOnly"
				v-show="isHandlePlusVisible"
				:data-plus-type="plusType"
				:line-size="plusLineSize"
				:handle-classes="handleClasses"
				:type="plusType"
				@mouseenter="onMouseEnter"
				@mouseleave="onMouseLeave"
				@click:plus="onClickAdd"
			/>
		</Transition>
	</div>
</template>

<style lang="scss" module>
.handle {
	display: flex;
	flex-direction: row;
	align-items: center;
	justify-content: center;

	&.connected .label {
		max-width: 96px;
	}
}

.label {
	position: absolute;
	background: var(--canvas--label--color--background);
	z-index: 1;
	max-width: calc(100% - var(--spacing--md) - 24px);
	white-space: nowrap;
	text-overflow: ellipsis;
	overflow: hidden;
}

.required .label::after {
	content: '*';
	color: var(--color--danger);
}

.outputLabel {
	top: 50%;
	left: var(--spacing--md);
	/* stylelint-disable-next-line @n8n/css-var-naming */
	transform: translate(0, -50%) scale(var(--canvas-zoom-compensation-factor, 1));
	transform-origin: center left;
	font-size: var(--font-size--2xs);
	color: var(--canvas--label--color);
}

.runDataLabel {
	position: absolute;
	top: 50%;
	/* stylelint-disable-next-line @n8n/css-var-naming */
	left: calc(50% * var(--canvas-zoom-compensation-factor, 1));
	/* stylelint-disable-next-line @n8n/css-var-naming */
	transform: translate(-50%, -50%) scale(var(--canvas-zoom-compensation-factor, 1))
		translate(0, -100%);
	font-size: var(--font-size--xs);
	color: var(--color--text);
}
</style>

<style lang="scss">
.canvas-node-handle-main-output-enter-active,
.canvas-node-handle-main-output-leave-active {
	transform-origin: 0 center;
	transition-property: transform, opacity;
	transition-duration: 0.2s;
	transition-timing-function: ease;
}

.canvas-node-handle-main-output-enter-from,
.canvas-node-handle-main-output-leave-to {
	transform: scale(0);
	opacity: 0;
}
</style>
