import { HighlightStyle, syntaxHighlighting } from '@codemirror/language';
import { EditorView } from '@codemirror/view';
import { tags } from '@lezer/highlight';

/**
 * Light theme based on Tomorrow theme by Chris Kempson
 * https://github.com/vadimdemedes/thememirror/blob/main/source/themes/tomorrow.ts
 *
 * Dark theme based on Dracula theme by Zeno Rocha
 * https://github.com/vadimdemedes/thememirror/blob/main/source/themes/dracula.ts
 */

const BASE_STYLING = {
	fontSize: '0.8em',
	fontFamily: "Menlo, Consolas, 'DejaVu Sans Mono', monospace !important",
	maxHeight: '400px',
	tooltip: {
		maxWidth: '250px',
		lineHeight: '1.3em',
	},
	diagnosticButton: {
		backgroundColor: 'inherit',
		lineHeight: '1em',
		textDecoration: 'underline',
		marginLeft: '0.2em',
		cursor: 'pointer',
	},
};

interface ThemeSettings {
	isReadOnly?: boolean;
	maxHeight?: string;
	minHeight?: string;
	rows?: number;
	highlightColors?: 'default' | 'html';
}

export const codeNodeEditorTheme = ({
	isReadOnly,
	minHeight,
	maxHeight,
	rows,
	highlightColors,
}: ThemeSettings) => [
	EditorView.theme({
		'&': {
			'font-size': BASE_STYLING.fontSize,
			border: 'var(--border-base)',
			borderRadius: 'var(--border-radius-base)',
			backgroundColor: 'var(--color-code-background)',
			color: 'var(--color-code-foreground)',
			height: '100%',
		},
		'.cm-content': {
			fontFamily: BASE_STYLING.fontFamily,
			caretColor: isReadOnly ? 'transparent' : 'var(--color-code-caret)',
		},
		'.cm-cursor, .cm-dropCursor': {
			borderLeftColor: 'var(--color-code-caret)',
		},
		'&.cm-focused .cm-selectionBackgroundm .cm-selectionBackground, .cm-content ::selection': {
			backgroundColor: 'var(--color-code-selection)',
		},
		'&.cm-editor': {
			...(isReadOnly ? { backgroundColor: 'var(--color-code-background-readonly)' } : {}),
			borderColor: 'var(--border-color-base)',
		},
		'&.cm-editor.cm-focused': {
			outline: 'none',
			borderColor: 'var(--color-secondary)',
		},
		'.cm-activeLine': {
			backgroundColor: 'var(--color-code-lineHighlight)',
		},
		'.cm-activeLineGutter': {
			backgroundColor: 'var(--color-code-lineHighlight)',
		},
		'.cm-gutters': {
			backgroundColor: isReadOnly
				? 'var(--color-code-background-readonly)'
				: 'var(--color-code-gutterBackground)',
			color: 'var(--color-code-gutterForeground)',
			borderRadius: 'var(--border-radius-base)',
			borderRightColor: 'var(--border-color-base)',
		},
		'.cm-tooltip': {
			maxWidth: BASE_STYLING.tooltip.maxWidth,
			lineHeight: BASE_STYLING.tooltip.lineHeight,
		},
		'.cm-scroller': {
			overflow: 'auto',
			maxHeight: maxHeight ?? '100%',
			...(isReadOnly
				? {}
				: { minHeight: rows && rows !== -1 ? `${Number(rows + 1) * 1.3}em` : 'auto' }),
		},
		'.cm-gutter,.cm-content': {
			minHeight: rows && rows !== -1 ? 'auto' : (minHeight ?? 'calc(35vh - var(--spacing-2xl))'),
		},
		'.cm-diagnosticAction': {
			backgroundColor: BASE_STYLING.diagnosticButton.backgroundColor,
			color: 'var(--color-primary)',
			lineHeight: BASE_STYLING.diagnosticButton.lineHeight,
			textDecoration: BASE_STYLING.diagnosticButton.textDecoration,
			marginLeft: BASE_STYLING.diagnosticButton.marginLeft,
			cursor: BASE_STYLING.diagnosticButton.cursor,
		},
		'.cm-diagnostic-error': {
			backgroundColor: 'var(--color-background-base)',
		},
		'.cm-diagnosticText': {
			color: 'var(--color-text-base)',
		},
	}),
	highlightColors === 'html'
		? syntaxHighlighting(
				HighlightStyle.define([
					{ tag: tags.keyword, color: '#c678dd' },
					{
						tag: [tags.name, tags.deleted, tags.character, tags.propertyName, tags.macroName],
						color: '#e06c75',
					},
					{ tag: [tags.function(tags.variableName), tags.labelName], color: '#61afef' },
					{
						tag: [tags.color, tags.constant(tags.name), tags.standard(tags.name)],
						color: '#d19a66',
					},
					{ tag: [tags.definition(tags.name), tags.separator], color: '#abb2bf' },
					{
						tag: [
							tags.typeName,
							tags.className,
							tags.number,
							tags.changed,
							tags.annotation,
							tags.modifier,
							tags.self,
							tags.namespace,
						],
						color: '#e06c75',
					},
					{
						tag: [
							tags.operator,
							tags.operatorKeyword,
							tags.url,
							tags.escape,
							tags.regexp,
							tags.link,
							tags.special(tags.string),
						],
						color: '#56b6c2',
					},
					{ tag: [tags.meta, tags.comment], color: '#7d8799' },
					{ tag: tags.strong, fontWeight: 'bold' },
					{ tag: tags.emphasis, fontStyle: 'italic' },
					{ tag: tags.strikethrough, textDecoration: 'line-through' },
					{ tag: tags.link, color: '#7d8799', textDecoration: 'underline' },
					{ tag: tags.heading, fontWeight: 'bold', color: '#e06c75' },
					{ tag: [tags.atom, tags.bool, tags.special(tags.variableName)], color: '#d19a66' },
					{ tag: [tags.processingInstruction, tags.string, tags.inserted], color: '#98c379' },
					{ tag: tags.invalid, color: 'red', 'font-weight': 'bold' },
				]),
			)
		: syntaxHighlighting(
				HighlightStyle.define([
					{
						tag: tags.comment,
						color: 'var(--color-code-tags-comment)',
					},
					{
						tag: [tags.string, tags.special(tags.brace)],
						color: 'var(--color-code-tags-string)',
					},
					{
						tag: [tags.number, tags.self, tags.bool, tags.null],
						color: 'var(--color-code-tags-primitive)',
					},
					{
						tag: tags.keyword,
						color: 'var(--color-code-tags-keyword)',
					},
					{
						tag: tags.operator,
						color: 'var(--color-code-tags-operator)',
					},
					{
						tag: [
							tags.variableName,
							tags.propertyName,
							tags.attributeName,
							tags.regexp,
							tags.className,
							tags.typeName,
						],
						color: 'var(--color-code-tags-variable)',
					},
					{
						tag: [
							tags.definition(tags.typeName),
							tags.definition(tags.propertyName),
							tags.function(tags.variableName),
						],
						color: 'var(--color-code-tags-definition)',
					},
				]),
			),
];
