<template>
	<div ref="root" class="ph-no-capture" data-test-id="inline-expression-editor-output"></div>
</template>

<script lang="ts">
import Vue, { PropType } from 'vue';
import { EditorView } from '@codemirror/view';
import { EditorState } from '@codemirror/state';

import { highlighter } from '@/plugins/codemirror/resolvableHighlighter';
import { outputTheme } from './theme';

import type { Plaintext, Resolved, Segment } from '@/types/expressions';

export default Vue.extend({
	name: 'InlineExpressionEditorOutput',
	props: {
		segments: {
			type: Array as PropType<Segment[]>,
		},
	},
	watch: {
		segments() {
			if (!this.editor) return;

			this.editor.dispatch({
				changes: { from: 0, to: this.editor.state.doc.length, insert: this.resolvedExpression },
			});

			highlighter.addColor(this.editor, this.resolvedSegments);
			highlighter.removeColor(this.editor, this.plaintextSegments);
		},
	},
	data() {
		return {
			editor: null as EditorView | null,
		};
	},
	mounted() {
		this.editor = new EditorView({
			parent: this.$refs.root as HTMLDivElement,
			state: EditorState.create({
				doc: this.resolvedExpression,
				extensions: [outputTheme(), EditorState.readOnly.of(true), EditorView.lineWrapping],
			}),
		});
	},
	destroyed() {
		this.editor?.destroy();
	},
	computed: {
		resolvedExpression(): string {
			return this.segments.reduce((acc, segment) => {
				acc += segment.kind === 'resolvable' ? segment.resolved : segment.plaintext;
				return acc;
			}, '');
		},
		plaintextSegments(): Plaintext[] {
			return this.segments.filter((s): s is Plaintext => s.kind === 'plaintext');
		},
		resolvedSegments(): Resolved[] {
			let cursor = 0;

			return this.segments
				.map((segment) => {
					segment.from = cursor;
					cursor +=
						segment.kind === 'plaintext'
							? segment.plaintext.length
							: // eslint-disable-next-line @typescript-eslint/no-explicit-any
							  (segment.resolved as any).toString().length;
					segment.to = cursor;
					return segment;
				})
				.filter((segment): segment is Resolved => segment.kind === 'resolvable');
		},
	},
	methods: {
		getValue() {
			return '=' + this.resolvedExpression;
		},
	},
});
</script>

<style lang="scss"></style>
