import { useMemo, useState } from 'react'
import PropTypes from 'prop-types'
import CodeMirror from '@uiw/react-codemirror'
import { javascript } from '@codemirror/lang-javascript'
import { python } from '@codemirror/lang-python'
import { json } from '@codemirror/lang-json'
import { css } from '@codemirror/lang-css'
import { html } from '@codemirror/lang-html'
import { markdown } from '@codemirror/lang-markdown'
import { sql } from '@codemirror/lang-sql'
import { java } from '@codemirror/lang-java'
import { cpp } from '@codemirror/lang-cpp'
import { rust } from '@codemirror/lang-rust'
import { go } from '@codemirror/lang-go'
import { php } from '@codemirror/lang-php'
import { yaml } from '@codemirror/lang-yaml'
import { xml } from '@codemirror/lang-xml'
import { oneDark } from '@codemirror/theme-one-dark'
import { fcTemplateLang } from '../../../codemirror/fcTemplateLang'
import { useThemeContext } from '../context/ThemeContext'
import { Button, Modal, Typography } from 'antd'

const { Link } = Typography

export default function CodeBlockEditor({
  code = '',
  language = 'javascript',
  style = {},
  className = '',
  readOnly = false,
  onChange = null,
  height = 'auto',
  showLineNumbers = true,
  disabled = false,
  minimal = false,
  autoCompleteObject = null
}) {
  const { isDarkMode } = useThemeContext()
  const [codeMirrorOpen, setCodeMirrorOpen] = useState(false)
  var editorCode = code

  if (typeof code == 'object' && language == 'json') {
    editorCode = JSON.stringify(code, null, 2)
  }

  // Map language to CodeMirror extension
  const languageExtension = useMemo(() => {
    switch (language.toLowerCase()) {
      case 'javascript':
      case 'js':
        return javascript()
      case 'python':
      case 'py':
        return python()
      case 'json':
        return json()
      case 'xml':
        return xml()
      case 'fctemplatelang':
      case 'ejs':
        return fcTemplateLang({ autoCompleteObject })
      case 'html':
        return html()
      case 'css':
        return css()
      case 'markdown':
      case 'md':
        return markdown()
      case 'sql':
        return sql()
      case 'java':
        return java()
      case 'cpp':
      case 'c++':
      case 'c':
        return cpp()
      case 'rust':
      case 'rs':
        return rust()
      case 'go':
        return go()
      case 'php':
        return php()
      case 'yaml':
      case 'yml':
        return yaml()
      default:
        return javascript() // Default fallback
    }
  }, [language, autoCompleteObject])

  const handleOnChange = (value) => {
    if (typeof code == 'object' && language == 'json') {
      onChange(JSON.parse(value))
    } else {
      onChange(value)
    }
  }

  const codeMirror = (
    <div
      style={{
        border: '1px solid #85858541',
        ...style
      }}
      className={className}
    >
      <CodeMirror
        value={editorCode}
        height={height}
        theme={isDarkMode ? oneDark : 'light'}
        extensions={[languageExtension]}
        readOnly={readOnly || disabled}
        onChange={handleOnChange}
        basicSetup={{
          lineNumbers: showLineNumbers,
          foldGutter: true,
          dropCursor: false,
          allowMultipleSelections: false,
          indentOnInput: false,
          syntaxHighlighting: true,
          bracketMatching: true,
          closeBrackets: true,
          autocompletion: !readOnly,
          rectangularSelection: false,
          crosshairCursor: false,
          highlightActiveLine: !readOnly,
          highlightSelectionMatches: false,
          closeBracketsKeymap: false,
          searchKeymap: false,
          foldKeymap: false,
          completionKeymap: !readOnly,
          lintKeymap: false
        }}
        style={{
          fontSize: '14px',
          fontFamily: 'Monaco, Menlo, "Ubuntu Mono", monospace'
        }}
      />
    </div>
  )

  return (
    <>
      {minimal ? (
        <div
          style={{ maxWidth: '300px' }}
          className='minimal-code-block-editor'
        >
          <Link
            onClick={() => {
              setCodeMirrorOpen(true)
            }}
          >
            <pre>{editorCode.slice(-64).trim()}...</pre>
          </Link>
          <Modal
            closeIcon={false}
            open={codeMirrorOpen}
            width={800}
            footer={
              <Button
                onClick={() => {
                  setCodeMirrorOpen(false)
                }}
              >
                Close
              </Button>
            }
          >
            {codeMirror}
          </Modal>
        </div>
      ) : (
        codeMirror
      )}
    </>
  )
}

CodeBlockEditor.propTypes = {
  code: PropTypes.oneOfType([PropTypes.string, PropTypes.object]).isRequired,
  language: PropTypes.oneOfType([
    PropTypes.string,
    PropTypes.arrayOf(PropTypes.string)
  ]),
  style: PropTypes.object,
  className: PropTypes.string,
  readOnly: PropTypes.bool,
  onChange: PropTypes.func,
  height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
  showLineNumbers: PropTypes.bool,
  disabled: PropTypes.bool,
  minimal: PropTypes.bool,
  autoCompleteObject: PropTypes.oneOfType([PropTypes.object, PropTypes.string])
}
