<script lang="ts">
    import { onMount } from "svelte";
    import { UploadOutline } from "flowbite-svelte-icons";
    import * as monaco from "monaco-editor";

    // Define a custom theme for PDF content stream highlighting
    monaco.editor.defineTheme("forge-dark", {
        base: "vs-dark",
        inherit: true,
        rules: [
            { token: 'comment', foreground: '#6A9955' },           // Green for comments
            { token: 'operator', foreground: '#bd4fdb' },          // Purple for graphics state operators
            { token: 'color-operator', foreground: '#61AFEF' },     // Blue for color operators
            { token: 'text-positioning', foreground: '#2c9f9f' },   // Dark cyan for text positioning
            { token: 'text-render', foreground: '#4cdcdc' },        // Light cyan for text rendering
            { token: 'text-state', foreground: '#2c9f9f' },         // Dark cyan for text state
            { token: 'path-construct', foreground: '#ffa500' },     // Orange for path construction
            { token: 'path-paint', foreground: '#ff6b6b' },         // Reddish for path painting
            { token: 'named-element', foreground: '#e1e1e1' },      // Light gray for named elements
            { token: 'hex-string', foreground: '#E06C75' },         // Red for hex strings
            { token: 'number', foreground: '#e1e1e1' },             // Light gray for numbers
            { token: 'matrix', foreground: '#ffd700' },             // Gold for matrices
            { token: 'marked-content', foreground: '#98c379' },     // Green for marked content
        ],
        colors: {
            "editor.background": "#1E1F22FF",
        },
    });

    let {
        stream_data,
        height,
        save,
    }: {
        height: number;
        save: (updated_data: string) => void;
        stream_data: string;
    } = $props();

    let editorContainer: HTMLElement;
    let editor: monaco.editor.IStandaloneCodeEditor;

    let isEdited = $state(false);
    let last_data: string | undefined = $state(undefined);

    onMount(() => {
        editor = monaco.editor.create(editorContainer, {
            value: "",
            language: 'pdf-content-stream',
            theme: "forge-dark",
            minimap: { enabled: false },
            scrollBeyondLastLine: false,
            fontSize: 14,
            automaticLayout: true,
        });

        loadContents(stream_data);

        editor.onDidChangeModelContent(() => {
            isEdited = editor.getValue() !== stream_data;
        });

        editor.addCommand(
            monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyS,
            (context, args) => {
                if (isEdited) {
                    save(editor.getValue());
                }
            },
        );

        window.addEventListener("keydown", (event) => {
            if ((event.ctrlKey || event.metaKey) && event.key === "s") {
                event.preventDefault();
            }
        });

        return () => {
            editor.dispose();
        };
    });

    $effect(() => {
        loadContents(stream_data);
    });

    function loadContents(stream_data: string | undefined) {
        if (!stream_data || !editor) return;

        if (last_data === stream_data) {
            return;
        }

        isEdited = false;
        last_data = stream_data;
        editor.setValue(stream_data);
    }
</script>

<div class="relative">
    <div bind:this={editorContainer} style:height={height + "px"}></div>
    {#if isEdited}
        <button onclick={() => save(editor.getValue())} class="save-button">
            <UploadOutline size="xl" />
        </button>
    {/if}
</div>

<style lang="postcss">
    .save-button {
        @apply p-2 bg-forge-sec text-forge-text border-t border-forge-bound cursor-pointer;
        position: absolute;
        right: 2em;
        bottom: 0px;
        width: 48px;
        height: 48px;
    }

    .save-button:hover {
        background-color: #3c3d41;
    }
</style>
