import EditorComponent from 'react-simple-code-editor';
import { highlight, languages } from 'prismjs/components/prism-core';
import 'prismjs/components/prism-clike';
import 'prismjs/components/prism-markup';
import 'prismjs/components/prism-javascript';
import 'prismjs/components/prism-css';
import 'prismjs/components/prism-json';
import 'prismjs/themes/prism-dark.css';
import { useEffect, useRef, useState } from 'react';

export default function CodeEditor({
    initialCode = '',
    highlightLanguage = 'js',
    onCodeSubmit = null,
    children = null,
    style = null,
    buttonComponent: ButtonComponent = null,
}: {
    initialCode: string;
    highlightLanguage?: string;
    children?: any;
    style?: any;
    buttonComponent?: any;
    onCodeSubmit?: (code: string) => Promise<void> | void;
}) {
    const [codeBuffer, setCodeBuffer] = useState(initialCode);
    const [code, setCode] = useState(initialCode);
    const [disabled, setDisabled] = useState(false);
    const cooldown = useRef(null);

    useEffect(() => {
        if (initialCode) setCode(initialCode);
    }, [initialCode]);

    return (
        <div style={style || {}}>
            <EditorComponent
                value={codeBuffer}
                onValueChange={(code) => {
                    setCodeBuffer(code);
                    // Wait for the user to stop typing
                    clearTimeout(cooldown.current);
                    setDisabled(true);
                    cooldown.current = setTimeout(() => {
                        setCode(code);
                        setDisabled(false);
                    }, 500);
                }}
                highlight={(code) => {
                    try {
                        // Make a switch statement for the language
                        switch (highlightLanguage) {
                            case 'html':
                                return highlight(code, languages.html);
                            case 'css':
                                return highlight(code, languages.css);
                            case 'js':
                                return highlight(code, languages.js);
                            case 'json':
                                return highlight(code, languages.json);
                        }
                    } catch (error) {}

                    return highlight(code, languages.js);
                }}
                padding={24}
                className="text-white"
                spellCheck
                style={{
                    fontFamily: '"Fira code", "Fira Mono", monospace',
                    fontSize: 12,
                    background: 'rgba(0,0,0,1)',
                }}
            />

            {children ? children : null}

            {ButtonComponent ? (
                <ButtonComponent
                    disabled={disabled}
                    onClick={() => {
                        onCodeSubmit(code);
                    }}
                />
            ) : (
                <div
                    style={{
                        flex: 'grid',
                    }}
                >
                    {onCodeSubmit ? (
                        <button
                            style={{
                                backgroundColor: 'rgba(0,0,0,1)',
                                color: 'white',
                                padding: '12px',
                                borderRadius: '12px',
                                border: '2px solid gray',
                            }}
                            disabled={disabled}
                            onClick={() => {
                                onCodeSubmit(code);
                            }}
                        >
                            Submit
                        </button>
                    ) : null}
                </div>
            )}
        </div>
    );
}
