<template>
	<div>
		<div :class="{ 'main-header': true, expanded: !uiStore.sidebarMenuCollapsed }">
			<div v-show="!hideMenuBar" class="top-menu">
				<WorkflowDetails :read-only="readOnly" />
				<TabBar
					v-if="onWorkflowPage"
					:items="tabBarItems"
					:active-tab="activeHeaderTab"
					@select="onTabSelected"
				/>
			</div>
		</div>
	</div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';
import type { Route, RouteLocationRaw } from 'vue-router';
import { mapStores } from 'pinia';
import type { IExecutionsSummary } from 'n8n-workflow';
import { pushConnection } from '@/mixins/pushConnection';
import WorkflowDetails from '@/components/MainHeader/WorkflowDetails.vue';
import TabBar from '@/components/MainHeader/TabBar.vue';
import {
	MAIN_HEADER_TABS,
	PLACEHOLDER_EMPTY_WORKFLOW_ID,
	STICKY_NODE_TYPE,
	VIEWS,
} from '@/constants';
import type { INodeUi, ITabBarItem } from '@/Interface';
import { workflowHelpers } from '@/mixins/workflowHelpers';
import { useNDVStore } from '@/stores/ndv.store';
import { useSourceControlStore } from '@/stores/sourceControl.store';
import { useUIStore } from '@/stores/ui.store';

export default defineComponent({
	name: 'MainHeader',
	components: {
		WorkflowDetails,
		TabBar,
	},
	mixins: [pushConnection, workflowHelpers],
	setup(props, ctx) {
		return {
			// eslint-disable-next-line @typescript-eslint/no-misused-promises
			...pushConnection.setup?.(props, ctx),
			// eslint-disable-next-line @typescript-eslint/no-misused-promises
			...workflowHelpers.setup?.(props, ctx),
		};
	},
	data() {
		return {
			activeHeaderTab: MAIN_HEADER_TABS.WORKFLOW,
			workflowToReturnTo: '',
			dirtyState: false,
		};
	},
	computed: {
		...mapStores(useNDVStore, useUIStore, useSourceControlStore),
		tabBarItems(): ITabBarItem[] {
			return [
				{ value: MAIN_HEADER_TABS.WORKFLOW, label: this.$locale.baseText('generic.editor') },
				{ value: MAIN_HEADER_TABS.EXECUTIONS, label: this.$locale.baseText('generic.executions') },
			];
		},
		activeNode(): INodeUi | null {
			return this.ndvStore.activeNode;
		},
		hideMenuBar(): boolean {
			return Boolean(this.activeNode && this.activeNode.type !== STICKY_NODE_TYPE);
		},
		workflowName(): string {
			return this.workflowsStore.workflowName;
		},
		currentWorkflow(): string {
			return this.$route.params.name || this.workflowsStore.workflowId;
		},
		onWorkflowPage(): boolean {
			return (
				this.$route.meta &&
				(this.$route.meta.nodeView || this.$route.meta.keepWorkflowAlive === true)
			);
		},
		activeExecution(): IExecutionsSummary {
			return this.workflowsStore.activeWorkflowExecution as IExecutionsSummary;
		},
		readOnly(): boolean {
			return this.sourceControlStore.preferences.branchReadOnly;
		},
	},
	watch: {
		$route(to, from) {
			this.syncTabsWithRoute(to);
		},
	},
	mounted() {
		this.dirtyState = this.uiStore.stateIsDirty;
		this.syncTabsWithRoute(this.$route);
	},
	methods: {
		syncTabsWithRoute(route: Route): void {
			if (
				route.name === VIEWS.EXECUTION_HOME ||
				route.name === VIEWS.WORKFLOW_EXECUTIONS ||
				route.name === VIEWS.EXECUTION_PREVIEW
			) {
				this.activeHeaderTab = MAIN_HEADER_TABS.EXECUTIONS;
			} else if (
				route.name === VIEWS.WORKFLOW ||
				route.name === VIEWS.NEW_WORKFLOW ||
				route.name === VIEWS.EXECUTION_DEBUG
			) {
				this.activeHeaderTab = MAIN_HEADER_TABS.WORKFLOW;
			}
			const workflowName = route.params.name;
			if (workflowName !== 'new') {
				this.workflowToReturnTo = workflowName;
			}
		},
		onTabSelected(tab: MAIN_HEADER_TABS, event: MouseEvent) {
			const openInNewTab = event.ctrlKey || event.metaKey;

			switch (tab) {
				case MAIN_HEADER_TABS.WORKFLOW:
					void this.navigateToWorkflowView(openInNewTab);
					break;

				case MAIN_HEADER_TABS.EXECUTIONS:
					void this.navigateToExecutionsView(openInNewTab);
					break;

				default:
					break;
			}
		},

		async navigateToWorkflowView(openInNewTab: boolean) {
			let routeToNavigateTo: RouteLocationRaw;
			if (!['', 'new', PLACEHOLDER_EMPTY_WORKFLOW_ID].includes(this.workflowToReturnTo)) {
				routeToNavigateTo = {
					name: VIEWS.WORKFLOW,
					params: { name: this.workflowToReturnTo },
				};
			} else {
				routeToNavigateTo = { name: VIEWS.NEW_WORKFLOW };
			}

			if (openInNewTab) {
				const { href } = this.$router.resolve(routeToNavigateTo);
				window.open(href, '_blank');
			} else if (this.$route.name !== routeToNavigateTo.name) {
				if (this.$route.name === VIEWS.NEW_WORKFLOW) {
					this.uiStore.stateIsDirty = this.dirtyState;
				}
				this.activeHeaderTab = MAIN_HEADER_TABS.WORKFLOW;
				await this.$router.push(routeToNavigateTo);
			}
		},

		async navigateToExecutionsView(openInNewTab: boolean) {
			const routeWorkflowId =
				this.currentWorkflow === PLACEHOLDER_EMPTY_WORKFLOW_ID ? 'new' : this.currentWorkflow;
			const routeToNavigateTo: RouteLocationRaw = this.activeExecution
				? {
						name: VIEWS.EXECUTION_PREVIEW,
						params: { name: routeWorkflowId, executionId: this.activeExecution.id },
				  }
				: {
						name: VIEWS.EXECUTION_HOME,
						params: { name: routeWorkflowId },
				  };

			if (openInNewTab) {
				const { href } = this.$router.resolve(routeToNavigateTo);
				window.open(href, '_blank');
			} else if (this.$route.name !== routeToNavigateTo.name) {
				this.dirtyState = this.uiStore.stateIsDirty;
				this.workflowToReturnTo = this.currentWorkflow;
				this.activeHeaderTab = MAIN_HEADER_TABS.EXECUTIONS;
				await this.$router.push(routeToNavigateTo);
			}
		},
	},
});
</script>

<style lang="scss">
.main-header {
	background-color: var(--color-background-xlight);
	height: $header-height;
	width: 100%;
	box-sizing: border-box;
	border-bottom: var(--border-width-base) var(--border-style-base) var(--color-foreground-base);
}

.top-menu {
	position: relative;
	display: flex;
	align-items: center;
	font-size: 0.9em;
	height: $header-height;
	font-weight: 400;
	padding: 0 var(--spacing-m) 0 var(--spacing-xs);
}
</style>
