import _objectSpread from "@babel/runtime/helpers/objectSpread";
import _regeneratorRuntime from "@babel/runtime/regenerator";
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
import _createClass from "@babel/runtime/helpers/createClass";
import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
import _inherits from "@babel/runtime/helpers/inherits";
import _assertThisInitialized from "@babel/runtime/helpers/assertThisInitialized";
import _defineProperty from "@babel/runtime/helpers/defineProperty";

var _dec, _class, _class2, _temp;

import React, { PureComponent } from 'react';
import { withTheme } from '@material-ui/core/styles';
import PropTypes from 'prop-types';
import { style, classes } from 'typestyle';
import { deg, rotateY, translateX } from 'csx';
import * as beautify from 'js-beautify';
import Button from '@material-ui/core/Button';
import Typography from '@material-ui/core/Typography';
import LinearProgress from '@material-ui/core/LinearProgress';
import AvStop from '@material-ui/icons/Stop';
import red from '@material-ui/core/colors/red';
import ContentReply from '@material-ui/icons/Reply';
import CardFloatingBar from '../CardFloatingBar';
import Editor from '../EditorCard/Editor';
import ImmutableFile from '../../File/ImmutableFile';
import FixAndMessage from '../EditorCard/FixAndMessage';
var cn = {
  root: style({
    display: 'flex',
    flexDirection: 'column'
  }),
  shoot: style({
    marginRight: 9,
    marginBottom: 4,
    transform: rotateY(deg(0))
  }),
  shooting: style({
    transform: rotateY(deg(180))
  }),
  label: style({
    fontSize: '.8rem'
  }),
  error: style({
    flex: '0 1 auto',
    margin: 0,
    padding: 8,
    backgroundColor: red['50'],
    color: red['500'],
    fontFamily: 'Consolas, "Liberation Mono", Menlo, Courier, monospace',
    overflow: 'scroll'
  }),
  restore: style({
    margin: 4
  }),
  blank: style({
    flex: 1
  })
};

var getCn = function getCn(props, state) {
  return {
    editor: style({
      position: 'relative',
      boxSizing: 'border-box',
      width: '100%',
      height: state.height,
      minHeight: 100,
      transform: translateX(state.shooting ? -500 : 0),
      opacity: state.shooting ? 0 : 1,
      transition: props.theme.transitions.create()
    })
  };
};

var ShotPane = (_dec = withTheme(), _dec(_class = (_temp = _class2 =
/*#__PURE__*/
function (_PureComponent) {
  _inherits(ShotPane, _PureComponent);

  function ShotPane() {
    var _getPrototypeOf2;

    var _this;

    _classCallCheck(this, ShotPane);

    for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
      args[_key] = arguments[_key];
    }

    _this = _possibleConstructorReturn(this, (_getPrototypeOf2 = _getPrototypeOf(ShotPane)).call.apply(_getPrototypeOf2, [this].concat(args)));

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "state", {
      shooting: false,
      height: 0,
      error: null,
      loading: false,
      canRestore: false,
      file: _this.props.file || shot(''),
      cardAnchorEl: null
    });

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "handleShot",
    /*#__PURE__*/
    _asyncToGenerator(
    /*#__PURE__*/
    _regeneratorRuntime.mark(function _callee() {
      return _regeneratorRuntime.wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              if (!_this.state.shooting) {
                _context.next = 2;
                break;
              }

              return _context.abrupt("return");

            case 2:
              _context.next = 4;
              return _this.shotCode();

            case 4:
              _this.setState({
                shooting: true
              });

            case 5:
            case "end":
              return _context.stop();
          }
        }
      }, _callee, this);
    })));

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "handleChange", function (cm) {
      var canRestore = cm.getValue() !== _this.state.file.text;

      _this.setState({
        canRestore: canRestore
      });
    });

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "handleRestore", function () {
      _this.codeMirror.setValue(_this.state.file.text);
    });

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "handleViewportChange", function (cm) {
      var lastLine = cm.lastLine() + 1;
      var height = cm.heightAtLine(lastLine, 'local'); // もしエディタの描画領域が広過ぎて ShotCard が画面からはみ出すなら, height を更新しない

      var cardAnchorEl = _this.state.cardAnchorEl;

      if (cardAnchorEl) {
        var offsetParent = cardAnchorEl.offsetParent,
            offsetTop = cardAnchorEl.offsetTop;
        var appendedHeight = height - _this.state.height;
        var containerHeight = offsetParent.clientHeight - parseInt(offsetParent.style.paddingTop, 10) - parseInt(offsetParent.style.paddingBottom, 10);

        if (offsetTop + appendedHeight >= containerHeight) {
          return;
        }
      }

      _this.setState({
        height: height
      });
    });

    return _this;
  }

  _createClass(ShotPane, [{
    key: "componentDidMount",
    value: function componentDidMount() {
      this.codeMirror.on('change', this.handleChange);
      this.codeMirror.on('swapDoc', this.handleChange);
      this.codeMirror.on('viewportChange', this.handleViewportChange);
      this.codeMirror.on('swapDoc', this.handleViewportChange);
      this.handleViewportChange(this.codeMirror);
      this.props.globalEvent.on('message.runCode', this.handleShot);
    }
  }, {
    key: "componentDidUpdate",
    value: function componentDidUpdate(prevProps, prevState) {
      var _this2 = this;

      if (prevProps.file !== this.props.file) {
        var file = this.props.file || shot('');
        this.setState({
          file: file
        });
      }

      if (!prevState.shooting && this.state.shooting) {
        // shooting アニメーションをもとにもどす
        setTimeout(function () {
          _this2.setState({
            shooting: false
          });
        }, 1000);
      }

      if (prevState.height !== this.state.height) {
        setTimeout(function () {
          // 表示可能領域が変わったので、トランジション後に再描画する
          if (_this2.codeMirror) {
            _this2.codeMirror.refresh();
          }
        }, 300);
      } // ShotCard の中にある最も下の要素を取得する


      var cardAnchorEl = document.querySelector('#ShotCard-BottomAnchor');

      if (!prevState.cardAnchorEl && cardAnchorEl) {
        this.setState({
          cardAnchorEl: cardAnchorEl
        });
      }
    }
  }, {
    key: "componentWillUnmount",
    value: function componentWillUnmount() {
      this.props.globalEvent.off('message.runCode', this.handleShot);
    }
  }, {
    key: "shotCode",
    value: function () {
      var _shotCode = _asyncToGenerator(
      /*#__PURE__*/
      _regeneratorRuntime.mark(function _callee2() {
        var text, configs, formatted, name, file, request;
        return _regeneratorRuntime.wrap(function _callee2$(_context2) {
          while (1) {
            switch (_context2.prev = _context2.next) {
              case 0:
                text = this.codeMirror ? this.codeMirror.getValue('\n') : this.state.file.text; // コードのフォーマット

                if (this.props.loadConfig('feelesrc').formatOnSendCode || false) {
                  // import .jsbeautifyrc
                  configs = this.props.loadConfig('jsbeautifyrc');
                  formatted = beautify.js(text, configs.js || {});
                  this.codeMirror.setValue(formatted);
                } // コードをファイルにする


                name = this.state.file.name;
                file = shot(text, name); // frame に shot をおくる

                request = {
                  query: 'shot',
                  value: _objectSpread({}, file)
                };
                this.props.globalEvent.emit('postMessage', request);

              case 6:
              case "end":
                return _context2.stop();
            }
          }
        }, _callee2, this);
      }));

      function shotCode() {
        return _shotCode.apply(this, arguments);
      }

      return shotCode;
    }()
  }, {
    key: "render",
    value: function render() {
      var _this3 = this;

      var dcn = getCn(this.props, this.state);
      var _this$props = this.props,
          localization = _this$props.localization,
          loadConfig = _this$props.loadConfig;
      var shooting = this.state.shooting; // TODO: Enter で実行か Shift-Enter で実行か

      var _loadConfig = loadConfig('feelesrc'),
          sendCodeOnEnter = _loadConfig.sendCodeOnEnter;

      var shootKey = sendCodeOnEnter ? 'Enter' : 'Ctrl-Enter';

      var extraKeys = _defineProperty({}, shootKey, this.handleShot);

      return React.createElement(React.Fragment, null, this.state.error ? React.createElement("pre", {
        className: cn.error
      }, this.state.error.message) : null, this.state.loading ? React.createElement(LinearProgress, null) : null, React.createElement(CardFloatingBar, null, React.createElement("span", null, localization.shotCard.title), React.createElement(Button, {
        variant: "contained",
        color: "secondary",
        onClick: this.handleRestore,
        className: cn.restore,
        disabled: !this.state.canRestore
      }, localization.shotCard.restore), React.createElement("div", {
        className: cn.blank
      }), React.createElement(Typography, {
        className: cn.label,
        color: "textSecondary"
      }, localization.shotCard.shoot), React.createElement(Button, {
        variant: "contained",
        color: "primary",
        disabled: this.state.shooting,
        onClick: this.handleShot,
        className: classes(cn.shoot, shooting && cn.shooting)
      }, localization.shotCard.button, this.state.shooting ? React.createElement(AvStop, null) : React.createElement(ContentReply, null))), React.createElement("div", {
        className: dcn.editor
      }, React.createElement(Editor, {
        isSelected: true,
        isCared: true,
        file: this.state.file,
        codemirrorRef: function codemirrorRef(ref) {
          return _this3.codeMirror = ref;
        },
        snippets: this.props.completes,
        extraKeys: extraKeys,
        lineNumbers: false,
        loadConfig: this.props.loadConfig,
        handleSetLinkObjects: this.props.handleSetLinkObjects,
        localization: this.props.localization
      })), React.createElement(FixAndMessage, {
        codemirror: this.codeMirror,
        localization: this.props.localization
      }));
    }
  }]);

  return ShotPane;
}(PureComponent), _defineProperty(_class2, "propTypes", {
  theme: PropTypes.object.isRequired,
  localization: PropTypes.object.isRequired,
  loadConfig: PropTypes.func.isRequired,
  file: PropTypes.object,
  completes: PropTypes.array,
  globalEvent: PropTypes.object.isRequired,
  handleSetLinkObjects: PropTypes.func.isRequired
}), _temp)) || _class);
export { ShotPane as default };

function shot() {
  var text = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
  var name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
  return new ImmutableFile({
    type: 'text/javascript',
    name: name,
    text: text
  });
}