// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
import React from "react";
import ReactDOM from "react-dom";
import {CodeEditor} from './codeeditor';
import {Beautify} from './beautify';
import {ZenModeOverlay} from './zenmodeoverlay';


// list of JSHINT errors to ignore: gets around problem of anonymous functions not being valid
const ignorableErrors = [
  'Missing name in function declaration.',
  "['{a}'] is better written in dot notation."
];

/**
 * A pre-packaged JS editor panel for use on the Edit Index / Mango pages. Includes options for a title, zen mode
 * icon and beautify button.
 */
export class CodeEditorPanel extends React.Component {
  static defaultProps = {
    id: 'code-editor',
    className: '',
    defaultCode: '',
    title: '',
    docLink: '',
    allowZenMode: true,
    syntaxMode: 'javascript',
    onCheatsheatIconClick: () => {},
    showCheatSheetIcon: false,
    setHeightToLineCount: true,
    blur () {}
  };

  getStoreState = () => {
    return {
      zenModeEnabled: false,
      code: this.props.defaultCode,
    };
  };

  UNSAFE_componentWillReceiveProps(nextProps) {
    if (nextProps.defaultCode !== this.props.defaultCode) {
      this.setState({ code: nextProps.defaultCode });
    }
  }

  getZenModeIcon = () => {
    if (this.props.allowZenMode) {
      return <span className="fonticon fonticon-resize-full zen-editor-icon" title="Enter Zen mode" onClick={this.enterZenMode}></span>;
    }
  };

  getCheatsheetIcon = () => {
    if (!this.props.showCheatSheetIcon) {
      return null;
    }
    return <span className="fonticon fonticon-bookmark cheatsheet-icon" title="Show cheatsheet" onClick={this.props.onCheatsheatIconClick}></span>;
  };

  getDocIcon = () => {
    if (this.props.docLink) {
      return (
        <a className="help-link"
          data-bypass="true"
          href={this.props.docLink}
          target="_blank"
          rel="noopener noreferrer"
        >
          <i className="fonticon-help-circled"></i>
        </a>
      );
    }
  };

  getZenModeOverlay = () => {
    if (this.state.zenModeEnabled) {
      return (
        <ZenModeOverlay
          defaultCode={this.state.code}
          mode={this.props.mode}
          ignorableErrors={ignorableErrors}
          onExit={this.exitZenMode} />
      );
    }
  };

  enterZenMode = () => {
    this.setState({
      zenModeEnabled: true,
      code: this.codeEditor.getValue()
    });
  };

  exitZenMode = (content) => {
    this.setState({ zenModeEnabled: false });
    this.getEditor().setValue(content);
  };

  getEditor = () => {
    return this.codeEditor;
  };

  getValue = () => {
    return this.getEditor().getValue();
  };

  beautify = (code) => {
    this.setState({ code: code });
    this.getEditor().setValue(code);
  };

  update = () => {
    this.getEditor().setValue(this.state.code);
  };

  state = this.getStoreState();

  render() {
    var classes = '';
    if (this.props.className) {
      classes = this.props.className;
    }
    const heightSettings = {};
    if (this.props.setHeightToLineCount) {
      heightSettings.setHeightToLineCount = true;
      heightSettings.maxLines = 1000;
    } else {
      heightSettings.setHeightToLineCount = false;
      heightSettings.minLines = 30;
    }
    return (
      <div className={classes}>
        <label>
          <span>{this.props.title}</span>
          {this.getDocIcon()}
          {this.getZenModeIcon()}
          {this.getCheatsheetIcon()}
        </label>
        <CodeEditor
          id={this.props.id}
          ref={node => this.codeEditor = node}
          mode={this.props.syntaxMode}
          defaultCode={this.state.code}
          showGutter={true}
          ignorableErrors={ignorableErrors}
          blur={this.props.blur}
          {...heightSettings}
        />
        <Beautify code={this.state.code} beautifiedCode={this.beautify} />
        {this.getZenModeOverlay()}
      </div>
    );
  }
}
