'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _react = require('react');

var _react2 = _interopRequireDefault(_react);

var _propTypes = require('prop-types');

var _propTypes2 = _interopRequireDefault(_propTypes);

var _lodash = require('lodash');

var _lodash2 = _interopRequireDefault(_lodash);

require('./CodeTester.css');

var _Editor = require('../Editor/Editor');

var _Editor2 = _interopRequireDefault(_Editor);

var _TestRunner = require('../TestRunner/TestRunner');

var _TestRunner2 = _interopRequireDefault(_TestRunner);

var _helpers = require('./helpers');

var _ExpandPaneIcon = require('../ExpandPaneIcon/ExpandPaneIcon');

var _ExpandPaneIcon2 = _interopRequireDefault(_ExpandPaneIcon);

var _Markdown = require('../Markdown/Markdown');

var _Markdown2 = _interopRequireDefault(_Markdown);

var _Console = require('../Console/Console');

var _Console2 = _interopRequireDefault(_Console);

var _InstructionsPanel = require('../InstructionsPanel/InstructionsPanel');

var _InstructionsPanel2 = _interopRequireDefault(_InstructionsPanel);

var _CodeTesterHeader = require('../CodeTesterHeader/CodeTesterHeader');

var _CodeTesterHeader2 = _interopRequireDefault(_CodeTesterHeader);

var _EditModeTabs = require('../EditModeTabs/EditModeTabs');

var _EditModeTabs2 = _interopRequireDefault(_EditModeTabs);

var _helpers2 = require('../../helpers');

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /* eslint no-unused-vars: 0 */


var CodeTester = function (_Component) {
  _inherits(CodeTester, _Component);

  function CodeTester(props) {
    _classCallCheck(this, CodeTester);

    var _this = _possibleConstructorReturn(this, (CodeTester.__proto__ || Object.getPrototypeOf(CodeTester)).call(this, props));

    _this.state = {
      code: '',
      lintedCode: '',
      verticalPanes: null,
      verticalPaneSizes: [],
      horizontalPanes: null,
      horizontalPaneSizes: [],
      expanded: null,
      consoleLogs: [],
      consoleErrors: [],
      consoleVisible: props.showConsole,
      consoleStyle: {
        right: '-40%'
      },
      testsVisible: false,
      selectedTabIndex: 0
    };
    _this.handleLintedCode = _this.handleLintedCode.bind(_this);
    _this.handleConsoleLog = _this.handleConsoleLog.bind(_this);
    _this.handleToggleConsole = _this.handleToggleConsole.bind(_this);
    _this.updateCode = _this.updateCode.bind(_this);
    _this.renderEditorPanel = _this.renderEditorPanel.bind(_this);
    _this.toggleInstructions = _this.toggleInstructions.bind(_this);
    _this.handleRunClick = _this.handleRunClick.bind(_this);
    _this.onTabSelect = _this.onTabSelect.bind(_this);
    return _this;
  }

  _createClass(CodeTester, [{
    key: 'handleLintedCode',
    value: function handleLintedCode(lintedCode) {
      // This function is only called if code passes linting rules
      var prevCode = this.state.lintedCode;
      // setState causes a re-render, so we need to make sure the code is different
      // from the code we already have.
      if (lintedCode !== prevCode) {
        this.setState({ lintedCode: lintedCode });
        this.props.onLintedCode(lintedCode);
      }
    }
  }, {
    key: 'updateCode',
    value: function updateCode(code) {
      /* This function is called when any code is entered,
        whether it passes linting rules or not.
      */
      var _props = this.props,
          editMode = _props.editMode,
          handleBoilerplateChange = _props.handleBoilerplateChange,
          onAnyCode = _props.onAnyCode;

      var prevCode = this.state.code;
      if (prevCode !== code) {
        this.setState({ code: code });
        onAnyCode(code);
      }
      if (editMode) {
        handleBoilerplateChange(code);
      }
    }
  }, {
    key: 'toggleInstructions',
    value: function toggleInstructions() {
      this.setState({ testsVisible: !this.state.testsVisible });
    }
  }, {
    key: 'handleToggleConsole',
    value: function handleToggleConsole() {
      var consoleVisible = this.state.consoleVisible;

      var consoleStyle = {};
      if (consoleVisible) {
        consoleStyle.right = '-40%';
      } else {
        consoleStyle.right = '0';
      }
      this.setState({ consoleVisible: !this.state.consoleVisible, consoleStyle: consoleStyle });
    }
  }, {
    key: 'handleConsoleLog',
    value: function handleConsoleLog(logs) {
      this.setState({ consoleLogs: logs });
    }
  }, {
    key: 'handleRunClick',
    value: function handleRunClick() {
      var _this2 = this;

      this.onTabSelect(1, null, null, function () {
        _this2.TestRunnerRef.handleNewCode();
      });
    }
  }, {
    key: 'onTabSelect',
    value: function onTabSelect(selectedTabIndex, prevIndex, event) {
      var cb = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : function () {};

      if (selectedTabIndex === 2) {
        this.setState(function (_ref) {
          var editMode = _ref.editMode;
          return { editMode: true, selectedTabIndex: selectedTabIndex };
        }, cb);
      } else {
        this.setState(function (_ref2) {
          var editMode = _ref2.editMode;
          return { editMode: false, selectedTabIndex: selectedTabIndex };
        }, cb);
      }
    }
  }, {
    key: 'renderEditorPanel',
    value: function renderEditorPanel() {
      var _props2 = this.props,
          initialCode = _props2.initialCode,
          instructions = _props2.instructions,
          handleInstructionsChange = _props2.handleInstructionsChange,
          handleTestSpecChange = _props2.handleTestSpecChange,
          handleBoilerplateChange = _props2.handleBoilerplateChange,
          handleReset = _props2.handleReset,
          showLints = _props2.showLints,
          testSpec = _props2.testSpec,
          hideEditorButtons = _props2.hideEditorButtons,
          headerText = _props2.headerText,
          subHeaderText = _props2.subHeaderText;
      var editMode = this.state.editMode;

      return editMode ? _react2.default.createElement(_EditModeTabs2.default, {
        initialCode: initialCode,
        showLints: showLints,
        instructions: instructions,
        testSpec: testSpec,
        handleInstructionsChange: handleInstructionsChange,
        handleTestSpecChange: handleTestSpecChange,
        handleBoilerplateChange: this.updateCode,
        handleLintedBoilerplateCode: this.handleLintedCode,
        handleReset: handleReset
      }) : _react2.default.createElement(
        'div',
        null,
        _react2.default.createElement(_CodeTesterHeader2.default, { headerText: headerText, subHeaderText: subHeaderText }),
        _react2.default.createElement(_Editor2.default, {
          code: initialCode,
          onValidCode: this.handleLintedCode,
          onAnyCode: this.updateCode,
          showLints: showLints,
          handleReset: handleReset,
          hideButtons: hideEditorButtons
        })
      );
    }
  }, {
    key: 'render',
    value: function render() {
      var _this3 = this;

      var _state = this.state,
          lintedCode = _state.lintedCode,
          verticalPanes = _state.verticalPanes,
          consoleStyle = _state.consoleStyle,
          testVisible = _state.testVisible,
          selectedTabIndex = _state.selectedTabIndex;
      var _props3 = this.props,
          onTestResults = _props3.onTestResults,
          testSpec = _props3.testSpec,
          instructions = _props3.instructions,
          autoRun = _props3.autoRun,
          iFrameUrl = _props3.iFrameUrl,
          testHandlerUrl = _props3.testHandlerUrl,
          onError = _props3.onError,
          infiniteLoopTimeout = _props3.infiniteLoopTimeout,
          submitEnabled = _props3.submitEnabled,
          onTestRunnerSubmitClick = _props3.onTestRunnerSubmitClick,
          hideEditorButtons = _props3.hideEditorButtons,
          markdownOptions = _props3.markdownOptions,
          className = _props3.className,
          toggleEditMode = _props3.toggleEditMode,
          handleReset = _props3.handleReset,
          editMode = _props3.editMode,
          handleUrlInput = _props3.handleUrlInput,
          handleGithubSubmit = _props3.handleGithubSubmit,
          committing = _props3.committing;

      return _react2.default.createElement(
        'div',
        { className: 'CodeTester ' + className },
        _react2.default.createElement(_InstructionsPanel2.default, {
          handleUrlInput: handleUrlInput,
          handleGithubSubmit: handleGithubSubmit,
          editMode: editMode,
          tabIndex: selectedTabIndex,
          onTabSelect: this.onTabSelect,
          instructions: instructions,
          markdownOptions: markdownOptions,
          testSpec: testSpec,
          lintedCode: lintedCode,
          onTestResults: onTestResults,
          handleConsoleLog: this.handleConsoleLog,
          autoRun: autoRun,
          iFrameUrl: iFrameUrl,
          testHandlerUrl: testHandlerUrl,
          onError: onError,
          infiniteLoopTimeout: infiniteLoopTimeout,
          submitEnabled: submitEnabled,
          onTestRunnerSubmitClick: onTestRunnerSubmitClick,
          toggleEditMode: toggleEditMode,
          handleReset: handleReset,
          onTestRunnerRef: function onTestRunnerRef(ref) {
            return _this3.TestRunnerRef = ref;
          },
          committing: committing
        }),
        _react2.default.createElement(
          'div',
          { className: 'right-code' },
          _react2.default.createElement(
            'div',
            { className: 'console-panel' },
            _react2.default.createElement(_Console2.default, {
              style: consoleStyle,
              logs: this.state.consoleLogs,
              onToggleConsole: this.handleToggleConsole,
              show: this.state.consoleVisible
            })
          ),
          _react2.default.createElement(
            'div',
            { className: 'right-panel-main' },
            this.renderEditorPanel()
          ),
          _react2.default.createElement(
            'div',
            { className: 'test-panel' },
            _react2.default.createElement(
              'button',
              { className: 'btn btn-lg btn-info', onClick: this.handleRunClick },
              'Run'
            ),
            _react2.default.createElement(
              'button',
              { className: 'btn btn-lg btn-success', onClick: onTestRunnerSubmitClick },
              'Submit'
            )
          )
        )
      );
    }
  }]);

  return CodeTester;
}(_react.Component);

CodeTester.propTypes = {
  autoRun: _propTypes2.default.bool,
  editMode: _propTypes2.default.bool,
  toggleEditMode: _propTypes2.default.func,
  handleUrlInput: _propTypes2.default.func,
  handleGithubSubmit: _propTypes2.default.func,
  handleBoilerplateChange: _propTypes2.default.func,
  handleInstructionsChange: _propTypes2.default.func,
  handleReset: _propTypes2.default.func,
  handleTestSpecChange: _propTypes2.default.func,
  infiniteLoopTimeout: _propTypes2.default.number,
  initialCode: _propTypes2.default.string,
  initialHorizontalPaneSizes: _propTypes2.default.arrayOf(_propTypes2.default.number),
  instructions: _propTypes2.default.string,
  iFrameUrl: _propTypes2.default.string.isRequired,
  onAnyCode: _propTypes2.default.func,
  onError: _propTypes2.default.func,
  onLintedCode: _propTypes2.default.func,
  onTestResults: _propTypes2.default.func,
  onTestRunnerSubmitClick: _propTypes2.default.func,
  showConsole: _propTypes2.default.bool,
  showLints: _propTypes2.default.bool,
  submitEnabled: _propTypes2.default.bool,
  testSpec: _propTypes2.default.string.isRequired,
  testHandlerUrl: _propTypes2.default.string,
  className: _propTypes2.default.string,
  hideEditorButtons: _propTypes2.default.bool,
  markdownOptions: _propTypes2.default.object,
  headerText: _propTypes2.default.string,
  subHeaderText: _propTypes2.default.string,
  committing: _propTypes2.default.bool
};

CodeTester.defaultProps = {
  onTestResults: function onTestResults(passCount, failCount, testDuration) {},
  onLintedCode: function onLintedCode(code) {},
  onAnyCode: function onAnyCode(code) {},
  initialCode: '',
  instructions: '',
  autoRun: false,
  showLints: true,
  editMode: false,
  submitEnabled: true,
  onError: function onError(err) {
    var message = _lodash2.default.get(err, 'message') ? err.message : 'Unknown';
    console.error('Code Tester Error: ', message);
  },
  infiniteLoopTimeout: 3000,
  showConsole: false,
  initialHorizontalPaneSizes: [70, 30],
  hideEditorButtons: false,
  markdownOptions: {}
};

exports.default = CodeTester;