import MonacoEditor from 'react-monaco-editor'
import React from 'react'
// import ReactDOM from 'react-dom'
import './code-editor.css'
import validate from './linter'

const handleError = (
  monaco,
  editor,
  nextErrors,
  nextCorrections
) => {
  if (!monaco) return;
  if (nextErrors && nextErrors.length > 0) {
    const errorMarkers = nextErrors
      .map(error => {
        if (error) {
          return {
            severity: monaco.Severity.Error,
            startColumn: 1,
            startLineNumber: error.line,
            endColumn: error.column,
            endLineNumber: error.line + 1,
            message: error.message,
          };
        }

        return null;
      })
      .filter(x => x);

    monaco.editor.setModelMarkers(editor.getModel(), 'error', errorMarkers);
  } else {
    monaco.editor.setModelMarkers(editor.getModel(), 'error', []);
  }

  if (nextCorrections.length > 0) {
    const correctionMarkers = nextCorrections
      .map(correction => {
        if (correction) {
          return {
            severity:
              correction.severity === 'warning'
                ? monaco.Severity.Warning
                : monaco.Severity.Notice,
            startColumn: correction.column,
            startLineNumber: correction.line,
            endColumn: 1,
            endLineNumber: correction.line + 1,
            message: correction.message,
            source: correction.source,
          };
        }

        return null;
      })
      .filter(x => x);

    monaco.editor.setModelMarkers(
      editor.getModel(),
      'correction',
      correctionMarkers
    );
  } else {
    monaco.editor.setModelMarkers(editor.getModel(), 'correction', []);
  }
}

class Editor extends React.Component {

  updateLintWarnings = (markers) => {
    this.m.editor.setModelMarkers(
      this.e.getModel(),
      'eslint',
      markers
    );
  }

  updateDimentions = () => {
    this.editor.editor.layout()
  }

  editorDidMount = (editor, monaco) => {
    this.e = editor
    this.m = monaco
  }

  componentDidMount = () => {
    window.addEventListener("resize", this.updateDimentions);
  }

  componentWillUnmount() {
    window.removeEventListener("resize", this.updateDimentions);
  }

  configureEditor = (editor, monaco) => {
    const compilerDefaults = {
      jsxFactory: 'React.createElement',
      reactNamespace: 'React',
      jsx: monaco.languages.typescript.JsxEmit.React,
      target: monaco.languages.typescript.ScriptTarget.ES2016,
      moduleResolution: monaco.languages.typescript.ModuleResolutionKind.NodeJs,
      module: monaco.languages.typescript.ModuleKind.System,
      noEmit: true,
      allowJs: true,
      typeRoots: ['node_modules/@types']
    }
    monaco.languages.typescript.javascriptDefaults.setCompilerOptions(
      compilerDefaults
    )
  }

  onChange = (newValue, e) => {
    const {language} = this.props
    if(language === 'javascript') {
      const markers = validate({code: newValue})
      this.updateLintWarnings(markers)
      return this.props.changeSrc(newValue, markers)
    }
    if(language === 'scss') {
      const markers = this.e.getModel().getAllDecorations().filter(({options}) => options.className === 'redsquiggly')
      return this.props.changeSrc(newValue, markers)
    }
    return this.props.changeSrc(newValue)
  }

  render() {
    const {src, language, height, width} = this.props
    const options = {
      selectOnLineNumbers: true
    }
    return (
      <MonacoEditor
        ref = {editor => this.editor = editor}
        width={width}
        height={height}
        language={language}
        theme="vs-dark"
        value={src}
        options={options}
        onChange={this.onChange}
        editorDidMount={this.editorDidMount}
      />
    )
  }
}

export default Editor
