import React, { Component } from 'react';
import brace from 'brace';
import AceEditor from 'react-ace';
import Select from 'react-select';

import {getOptionById} from 'utils/ioty'

import 'brace/ext/language_tools';
import 'brace/ext/static_highlight';
import 'brace/ext/keybinding_menu';
import 'brace/ext/emmet';
import 'brace/keybinding/vim';

import 'brace/mode/c_cpp';
import 'brace/mode/csharp';
import 'brace/mode/objectivec';
import 'brace/mode/javascript';
import 'brace/mode/python';
import 'brace/mode/java';
import 'brace/mode/ruby';
import 'brace/mode/golang';
import 'brace/mode/perl';
import 'brace/mode/clojure';
import 'brace/mode/scala';
import 'brace/mode/html';

import 'brace/theme/github';
import 'brace/theme/tomorrow';
import 'brace/theme/kuroir';
import 'brace/theme/twilight';
import 'brace/theme/xcode';
import 'brace/theme/textmate';
import 'brace/theme/monokai';
import 'brace/theme/cobalt';
import 'brace/theme/terminal';
import 'brace/theme/iplastic';
import 'brace/theme/dawn';
import 'brace/theme/eclipse';
import 'brace/theme/pastel_on_dark';
import 'brace/theme/solarized_dark';
import 'brace/theme/solarized_light';
import 'brace/theme/chrome';

var listOfProgrammingLanguage = {
  "c" : "c_lang",
  "c++" : "cpp_lang",
  "python" : "python"
}

const BLANK_STRING5 = '_____'
const RESPONSE_BLANK_CHARACTER = '|||'

export default class AceEditorComponent extends Component {
  constructor(props) {
    super(props)
    this.onChange = this.onChange.bind(this);
    this.handleProgrammingLanguageChange = this.handleProgrammingLanguageChange.bind(this);
    this.handleAceEditorThemeChange = this.handleAceEditorThemeChange.bind(this);
    this.handleRunCode = this.handleRunCode.bind(this);
    this.handleSubmitCode = this.handleSubmitCode.bind(this);
    this.handleAceEditorFontChange = this.handleAceEditorFontChange.bind(this);
    this.onRunCode = this.onRunCode.bind(this);
    this.loadPreviousCode = this.loadPreviousCode.bind(this)
    /**
     * onChanging code on code editor problem with speed writing so
     * i am using now local state
     */

     this.editor = null
    this.state = {
      code : ""
    }
  }

  static contextTypes = {
    router: React.PropTypes.object.isRequired
  };

  handleRunCode() {
    /**
     * onChanging code on code editor problem with speed writing so
     * i am using now local state
     */
    // this.props.aceEditorActions.sendCodeForExecution(this.props.aceEditorInfo.code);
    this.props.aceEditorActions.changeAceEditorIsLoading(true);
    this.props.aceEditorActions.sendCodeForExecution(
      this.state.code, this.props.aceEditorInfo.programmingLanguage, false);
  }

  onChange(value) {
    this.setState({
      code : value
    })
    /**
     * global state making the writing slow
     */
    // this.props.aceEditorActions.changeAceEditorCode(value);
  }
  handleProgrammingLanguageChange(options) {
    this.props.aceEditorActions.changeAceEditorProgrammingLanguage(options.value)
  }
  handleAceEditorThemeChange(options) {
    this.props.aceEditorActions.changeAceEditorTheme(options.value);
  }
  handleAceEditorFontChange (options) {
    this.props.aceEditorActions.changeAceEditorFontSize(options.value);
  }

  loadPreviousCode (codeString, userSelectedStepOptions, currentStep, lineNumbers) {
    if (userSelectedStepOptions !== undefined && userSelectedStepOptions !== null) {
      let blankOptions = [], option
      for (let i=0;i<currentStep;i++) {
        let currentStepDetails = this.props.steps[i]
        let blankWithId = RESPONSE_BLANK_CHARACTER + userSelectedStepOptions[i].blankId
        if (currentStepDetails.hasOwnProperty('codeBlank')) {
          if (currentStepDetails.codeBlank.blankType === 'TYPE_OPTIONS') {
            blankOptions = currentStepDetails.codeBlank.blankOptions
          }
          if (userSelectedStepOptions[i].blankOptionId !== -1 && currentStepDetails.codeBlank.blankType === 'TYPE_OPTIONS') {
            option = getOptionById(blankOptions, userSelectedStepOptions[i].blankOptionId)
            codeString = codeString.split(blankWithId).join(option.optionValue)
          } else if (currentStepDetails.codeBlank.blankType === 'TYPE_TEXT' && userSelectedStepOptions[i].hasOwnProperty('blankValue')) {
            codeString = codeString.replace(blankWithId, userSelectedStepOptions[i].blankValue)
          }
        }
      }
      codeString = codeString.replace(/\|\|\|[0-9]+/g, BLANK_STRING5)
      let currentStepBlankOptionId = userSelectedStepOptions[currentStep-1].blankOptionId
      let currentCodeString = codeString.split("\n").slice(lineNumbers[0]-1, lineNumbers[1]).join("\n")
      this.setState({
        code : `${currentCodeString}`
      }, function () {
        this.editor.navigateWordLeft()
        this.editor.find(currentStepBlankOptionId === -1 ?  BLANK_STRING5 : '', {caseSensitive : true})
        // this.editor.centerSelection()
      }.bind(this))
    }
  }
  componentWillReceiveProps(nextProps) {
    let codeString = '',
        currentCodeString = '',
        codeBlank = nextProps.currentStepDetails.codeBlank,
        lineNumbers = codeBlank.lineNumbers.split('-').map( (lineNumber) => Number(lineNumber))
    if (nextProps.codeData) {
      codeString = nextProps.codeData.codeString
      // currentCodeString = codeString.split("\n").slice(lineNumbers[0]-1, lineNumbers[1]).join("\n")
      this.loadPreviousCode(codeString, nextProps.userSelectedStepOptions, nextProps.currentStep, lineNumbers)
    }
  }
  componentDidMount() {
    this.editor = this.refs.iotyVLabCodeEditor.editor
    this.editor.getSession().setUseWrapMode(true);
    this.editor.setHighlightActiveLine(false);
    this.editor.setHighlightGutterLine(false);
    this.editor.container.style.pointerEvents = "none";
    this.props.aceEditorActions.setAceEditor(this.editor)
    this.props.aceEditorActions.changeAceEditorFontSize('14');
    this.editor.centerSelection()

    /*this.editor.renderer.$cursorLayer.element.style.opacity = 0;
    this.editor.session.setFoldStyle('manual');
    this.editor.getSession().removeAllListeners("guttermousedown");
    this.editor.getSession().removeAllListeners("gutterclick");
    this.editor.getSession().removeAllListeners("gutterdblclick");
    this.editor.getSession().removeAllListeners("guttermousemove");
    this.editor.getSession().removeAllListeners("click");
    this.editor.getSession().removeAllListeners("mousedown");*/
    // this.editor.container.webkitRequestFullscreen()    to get full screen
  }

  componentWillUnmount() {
    this.props.aceEditorActions.changeAceEditorFontSize('12');
  }

  handleSubmitCode(){
    this.props.aceEditorActions.changeAceEditorIsLoading(true);
    this.props.aceEditorActions.sendCodeForExecution(
      this.state.code, this.props.aceEditorInfo.programmingLanguage, true, this.onRunCode
    );
  }

  onRunCode(requestObject){
    console.log('onRunCode',requestObject);
   /* this.props.VLCommonActions.evaluateVLQAPI(
      requestObject, true,
      this.context.router, this.props.params);*/
  }

  render() {
    let output = this.props.aceEditorInfo.output;
    let message ;

    if(output.output || output.errors || output.time) {
      if(!output.errors.length>0){
         message =
          <div className= {this.props.aceEditorInfo.isLoading ? 'hidden' : 'text-success'}>
            <p>{output.output}</p>
          </div>;
      }else{
         message =
          <div className= {this.props.aceEditorInfo.isLoading ? 'hidden' : 'text-danger'}>
            <h5>An error occured</h5>
            <p>{output.errors}</p>
          </div>;
      }

    }


    let optionsforTheme = [
      { value : "monokai", label : "monokai"},
      { value : "github", label : "github"},
      { value : "tomorrow", label : "tomorrow"},
      { value : "kuroir", label : "kuroir"},
      { value : "twilight", label : "twilight"},
      { value : "xcode", label : "xcode"},
      { value : "textmate", label : "textmate"},
      { value : "cobalt", label : "cobalt"},
      { value : "chrome", label : "chrome"},
      { value : "terminal", label : "terminal"},
      { value : "iplastic", label : "iplastic"},
      { value : "dawn", label : "dawn"},
      { value : "eclipse", label : "eclipse"},
      { value : "pastel_on_dark", label : "Pastel on dark"},
      { value : "solarized_light", label : "Solarized light"},
      { value : "solarized_dark", label : "Solarized dark"},
    ]

//c_cpp
    let optionsforlanguage = [
      { value : "c_lang", label : "C" },
      { value : "cpp_lang", label : "C++" },
      { value : "python", label : "Python" }
    ]
    let optionsforFontSize = [
      { value : "8", label : "8px" },
      { value : "10", label : "10px" },
      { value : "12", label : "12px" },
      { value : "14", label : "14px" },
      { value : "16", label : "16px" },
      { value : "18", label : "18px" },
      { value : "20", label : "20px" },
      { value : "22", label : "22px" },
      { value : "24", label : "24px" },
    ]

    let programmingLanguage;
    switch(this.props.aceEditorInfo.programmingLanguage) {
      case 'c_lang':
      case 'cpp_lang':
        programmingLanguage = 'c_cpp';
        break;
      default :
        programmingLanguage = this.props.aceEditorInfo.programmingLanguage;
    }
    let bgColor = '#fff';
    switch(this.props.aceEditorInfo.aceEditorTheme) {
      case 'github':
      case 'chrome':
      case 'tomorrow':
      case 'eclipse':
      case 'xcode':
      case 'textmate':
        bgColor = "#fff" ;
        break;
      case 'kuroir':
        bgColor = "#E8E9E8";
        break;
      case 'twilight':
        bgColor = "#141414"
        break;
      case 'monokai':
        bgColor = "#272822";
        break;
      case 'cobalt':
        bgColor = "#002240";
        break;
      case 'terminal':
        bgColor = "#000";
        break;
      case 'iplastic':
        bgColor = "#eeeeee";
        break;
      case 'dawn':
          bgColor = "#F9F9F9";
          break;
      case 'pastel_on_dark':
          bgColor = "#2C2828";
          break;
      case 'solarized_dark':
          bgColor = "#002B36";
          break;
      case 'solarized_light':
          bgColor = "#FDF6E3";
          break;
    }
    let bgColorObj = {
      background : bgColor
    }
    return (
      <div className="IoTyVLabAceEditorComponent">
        <div className="row">
          <div className="col-md-12">
              <div className="col-md-12">
                <div className="row">
                  <div className="col-md-12">
                    <div className="row">
                      <div className="aceEditor">
                        <div className={this.props.aceEditorInfo.isLoading ? "aceEditorOutputLoader" : "hidden"}>
                          <img id="loader" src={"/images/Loading.png"}/>
                        </div>
                        <AceEditor
                          mode='c_cpp'
                          theme='monokai'
                          onChange={this.onChange}
                          height="230px"
                          width="100%"
                          value={this.state.code}
                          name="IoTyVLabCodeEditor"
                          readOnly={true}
                          ref='iotyVLabCodeEditor'
                          setOptions={{
                            enableBasicAutocompletion: true,
                            enableLiveAutocompletion: true,
                            enableSnippets : true,
                            tabSize: 4,
                            fontSize: 16,
                            showGutter: true
                          }}
                          editorProps={{$blockScrolling: true}} />
                      </div>
                    </div>
                  </div>
                </div>
              </div>
          </div>
        </div>
      </div>
    );
  }
}