'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 _EditModeTabs = require('../EditModeTabs/EditModeTabs');

var _EditModeTabs2 = _interopRequireDefault(_EditModeTabs);

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: true
    };
    _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.renderCenterPane = _this.renderCenterPane.bind(_this);
    return _this;
  }

  _createClass(CodeTester, [{
    key: 'componentDidMount',
    value: function componentDidMount() {
      var verticalPanes = (0, _helpers.initSplit)(['#code-tester-instructions', '#code-tester-editor', '#code-tester-test-runner'], { sizes: [33, 33, 34], minSize: [0, 0, 0] });
      var horizontalPanes = (0, _helpers.initSplit)(['.code-tester-split-top', '.code-tester-split-bottom'], { sizes: [70, 30], direction: 'vertical', minSize: [400, 50] });
      this.setState({ verticalPanes: verticalPanes, horizontalPanes: horizontalPanes });
    }
  }, {
    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);
      }
      // send clean code to test runner
      // save to localStorage
    }
  }, {
    key: 'updateCode',
    value: function updateCode(code) {
      /* This function is called when any code is entered,
        whether it passes linting rules or not.
      */
      var prevCode = this.state.code;
      if (prevCode !== code) {
        this.setState({ code: code });
        this.props.onAnyCode(code);
      }
    }
  }, {
    key: 'toggleFullWidth',
    value: function toggleFullWidth(targetPaneNum) {
      var verticalPanes = this.state.verticalPanes;

      if (this.state.expanded === null) {
        var verticalPaneSizes = verticalPanes.getSizes();
        this.setState({ expanded: targetPaneNum, verticalPaneSizes: verticalPaneSizes });
        _lodash2.default.range(0, verticalPaneSizes.length).filter(function (paneId) {
          return paneId !== targetPaneNum;
        }).forEach(function (paneId) {
          verticalPanes.collapse(paneId);
        });
      } else {
        verticalPanes.setSizes(this.state.verticalPaneSizes);
        this.setState({ expanded: null });
      }
    }
  }, {
    key: 'handleToggleConsole',
    value: function handleToggleConsole() {
      var _state = this.state,
          consoleVisible = _state.consoleVisible,
          horizontalPanes = _state.horizontalPanes,
          lastSizes = _state.horizontalPaneSizes;

      var horizontalPaneSizes = void 0;
      if (consoleVisible) {
        horizontalPaneSizes = horizontalPanes.getSizes();
        horizontalPanes.setSizes([93, 7]);
      } else {
        horizontalPanes.setSizes(lastSizes);
      }
      this.setState({ consoleVisible: !this.state.consoleVisible, horizontalPaneSizes: horizontalPaneSizes });
    }
  }, {
    key: 'handleConsoleLog',
    value: function handleConsoleLog(logs) {
      this.setState({ consoleLogs: logs });
    }
  }, {
    key: 'renderCenterPane',
    value: function renderCenterPane() {
      var _props = this.props,
          editMode = _props.editMode,
          initialCode = _props.initialCode,
          instructions = _props.instructions,
          handleInstructionsChange = _props.handleInstructionsChange,
          handleTestSpecChange = _props.handleTestSpecChange,
          showLints = _props.showLints,
          testSpec = _props.testSpec;

      return editMode ? _react2.default.createElement(_EditModeTabs2.default, {
        initialCode: initialCode,
        showLints: showLints,
        instructions: instructions,
        testSpec: testSpec,
        handleInstructionsChange: handleInstructionsChange,
        handleTestSpecChange: handleTestSpecChange
      }) : _react2.default.createElement(_Editor2.default, {
        code: initialCode,
        onValidCode: this.handleLintedCode,
        onAnyCode: this.updateCode,
        showLints: showLints
      });
    }
  }, {
    key: 'render',
    value: function render() {
      var _state2 = this.state,
          lintedCode = _state2.lintedCode,
          verticalPanes = _state2.verticalPanes;
      var _props2 = this.props,
          onTestResults = _props2.onTestResults,
          testSpec = _props2.testSpec,
          instructions = _props2.instructions,
          autoRun = _props2.autoRun,
          iFrameUrl = _props2.iFrameUrl,
          testHandlerUrl = _props2.testHandlerUrl,
          onError = _props2.onError,
          infiniteLoopTimeout = _props2.infiniteLoopTimeout;

      var handleTestResults = this.props.onTestResults;
      return _react2.default.createElement(
        'div',
        { className: 'CodeTester' },
        _react2.default.createElement(
          'div',
          { className: 'outer-flex-container' },
          _react2.default.createElement(
            'div',
            { className: 'inner-flex-container code-tester-split-top outer-split-item' },
            _react2.default.createElement(
              'div',
              { className: 'inner-flex-item split', id: 'code-tester-instructions' },
              _react2.default.createElement(_Markdown2.default, { markdown: instructions })
            ),
            _react2.default.createElement(
              'div',
              { className: 'inner-flex-item split', id: 'code-tester-editor' },
              _react2.default.createElement(_ExpandPaneIcon2.default, { paneExpander: this.toggleFullWidth.bind(this, 1) }),
              this.renderCenterPane()
            ),
            _react2.default.createElement(
              'div',
              { className: 'inner-flex-item split test-runner-container', id: 'code-tester-test-runner' },
              _react2.default.createElement(_TestRunner2.default, {
                testSpec: testSpec,
                codeToTest: lintedCode,
                onTestResults: handleTestResults,
                onConsoleLog: this.handleConsoleLog,
                autoRun: autoRun,
                iFrameUrl: iFrameUrl,
                testHandlerUrl: testHandlerUrl,
                onError: onError,
                infiniteLoopTimeout: infiniteLoopTimeout
              })
            )
          ),
          _react2.default.createElement(
            'div',
            { className: 'code-tester-split-bottom outer-split-item' },
            _react2.default.createElement(_Console2.default, { logs: this.state.consoleLogs, onToggleConsole: this.handleToggleConsole, show: this.state.consoleVisible })
          )
        )
      );
    }
  }]);

  return CodeTester;
}(_react.Component);

CodeTester.propTypes = {
  autoRun: _propTypes2.default.bool,
  iFrameUrl: _propTypes2.default.string.isRequired,
  initialCode: _propTypes2.default.string,
  instructions: _propTypes2.default.string,
  onAnyCode: _propTypes2.default.func,
  onLintedCode: _propTypes2.default.func,
  onTestResults: _propTypes2.default.func,
  showLints: _propTypes2.default.bool,
  testSpec: _propTypes2.default.string.isRequired,
  handleInstructionsChange: _propTypes2.default.func,
  handleTestSpecChange: _propTypes2.default.func,
  handleBoilerplateChange: _propTypes2.default.func,
  editMode: _propTypes2.default.bool,
  testHandlerUrl: _propTypes2.default.string,
  onError: _propTypes2.default.func,
  infiniteLoopTimeout: _propTypes2.default.number
};

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

exports.default = CodeTester;