import _extends from "@babel/runtime/helpers/extends";
import _objectSpread from "@babel/runtime/helpers/objectSpread";
import _regeneratorRuntime from "@babel/runtime/regenerator";
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
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, _dec2, _class, _class2, _temp;

import React, { Component } from 'react';
import { withTheme } from '@material-ui/core/styles';
import PropTypes from 'prop-types';
import { style } from 'typestyle';
import EventEmitter from 'eventemitter2';
import Snackbar from '@material-ui/core/Snackbar';
import jsyaml from 'js-yaml';
import IconButton from '@material-ui/core/IconButton';
import MenuItem from '@material-ui/core/MenuItem';
import ListItemIcon from '@material-ui/core/ListItemIcon';
import ListItemText from '@material-ui/core/ListItemText';
import Drawer from '@material-ui/core/Drawer';
import NavigationArrowBack from '@material-ui/icons/ArrowBack';
import ToggleCheckBox from '@material-ui/icons/CheckBox';
import ToggleCheckBoxOutlineBlank from '@material-ui/icons/CheckBoxOutlineBlank';
import MigrateAsset from './MigrateAsset';

var tryParseYAML = function tryParseYAML(text) {
  var defaultValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};

  try {
    return jsyaml.safeLoad(text);
  } catch (e) {
    console.error(e);
    return defaultValue;
  }
};

var tryParseJSON = function tryParseJSON(text) {
  var defaultValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};

  try {
    return JSON.parse(text);
  } catch (e) {
    console.error(e);
    return defaultValue;
  }
};

import { configs } from '../File/';
import codemirrorStyle from '../js/codemirrorStyle';
import * as MonitorTypes from '../utils/MonitorTypes';
import Menu from '../Menu/';
import FileDialog from '../FileDialog/';
import CardContainer from '../Cards/CardContainer';
import icons from './icons';
import withFiles from '../store/withFiles';
var cn = {
  root: style({
    position: 'relative',
    width: '100%',
    height: '100%',
    display: 'flex',
    flexDirection: 'column',
    lineHeight: 1.15
  }),
  alignRight: style({
    textAlign: 'right'
  }),
  drawer: {
    paper: style({
      position: 'absolute'
    })
  }
};
var Main = (_dec = withTheme(), _dec2 = withFiles({}), _dec(_class = _dec2(_class = (_temp = _class2 =
/*#__PURE__*/
function (_Component) {
  _inherits(Main, _Component);

  function Main() {
    var _getPrototypeOf2;

    var _this;

    _classCallCheck(this, Main);

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

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

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "state", {
      openSidebar: false,
      monitorType: _this.props.autoFullScreen ? MonitorTypes.FullScreen : MonitorTypes.Card,
      reboot: false,
      href: 'index.html',
      notice: null,
      // Advanced Mode
      showAll: false,
      // card =(emit)=> globalEvent =(on)=> card
      globalEvent: new EventEmitter({
        wildcard: true
      }),
      isExpandingEditorCard: false // 集中執筆モード的な

    });

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "_configs", new Map());

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "getConfig", function (key) {
      if (_this._configs.has(key)) {
        return _this._configs.get(key);
      } else {
        var _configs$get = configs.get(key),
            test = _configs$get.test,
            defaultValue = _configs$get.defaultValue,
            multiple = _configs$get.multiple,
            bundle = _configs$get.bundle;

        var pred = function pred(file) {
          return !file.isTrashed && test.test(file.name);
        };

        var value = {};

        if (multiple) {
          var files = _this.props.files.filter(pred);

          value = bundle(files);
        } else {
          var file = _this.props.files.find(pred);

          try {
            value = JSON.parse(file.text);
          } catch (error) {
            value = defaultValue;
          }
        }

        _this._configs.set(key, value);

        return value;
      }
    });

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "resetConfig", function (fileName) {
      // Refresh config
      var _iteratorNormalCompletion = true;
      var _didIteratorError = false;
      var _iteratorError = undefined;

      try {
        for (var _iterator = configs.entries()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
          var _step$value = _slicedToArray(_step.value, 2),
              key = _step$value[0],
              value = _step$value[1];

          if (value.test.test(fileName)) {
            _this._configs.delete(key);
          }
        }
      } catch (err) {
        _didIteratorError = true;
        _iteratorError = err;
      } finally {
        try {
          if (!_iteratorNormalCompletion && _iterator.return != null) {
            _iterator.return();
          }
        } finally {
          if (_didIteratorError) {
            throw _iteratorError;
          }
        }
      }
    });

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "loadConfig", function (ext) {
      var _ext = "**/*.".concat(ext);

      var json = "**/*.".concat(ext, ".json");
      var yaml = "**/*.".concat(ext, ".yml"); // TODO: オブジェクト（ハッシュ）以外も使えるようにする

      var values = [].concat( // .json (JSON)
      _this.props.glob(json, {
        dot: true
      }).map(function (file) {
        return tryParseJSON(file.text, {});
      }), // .yml (YAML)
      _this.props.glob(yaml, {
        dot: true
      }).map(function (file) {
        return tryParseYAML(file.text, {});
      }), // .(ext) (JSON)
      _this.props.glob(_ext, {
        dot: true
      }).map(function (file) {
        return tryParseJSON(file.text, {});
      }));
      return Object.assign.apply(Object, [{}].concat(_toConsumableArray(values)));
    });

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "handleTogglePopout", function () {
      var isPopout = _this.state.monitorType === MonitorTypes.Popout;

      _this.setState({
        reboot: true,
        monitorType: isPopout ? MonitorTypes.Card : MonitorTypes.Popout
      });
    });

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "handleToggleFullScreen", function () {
      var isFullScreen = _this.state.monitorType === MonitorTypes.FullScreen;

      _this.setState({
        monitorType: isFullScreen ? MonitorTypes.Card : MonitorTypes.FullScreen
      });
    });

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "setLocation", function (href) {
      _this.setState(function (prevState) {
        return {
          reboot: true,
          href: href || prevState.href
        };
      });
    });

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "handleShowNotice", function (notice) {
      return _this.setStatePromise({
        notice: notice
      });
    });

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "toggleShowAll", function () {
      return _this.setStatePromise({
        showAll: !_this.state.showAll
      });
    });

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "openFileDialog", function () {
      return console.info('openFileDialog has not be declared');
    });

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "handleFileDialog", function (ref) {
      return ref && (_this.openFileDialog = ref.open);
    });

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "toggleSidebar", function () {
      if (_this.props.mini) return; // mini の場合, stateless

      _this.setState({
        openSidebar: !_this.state.openSidebar
      });
    });

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "renderMenuItem", function (item, index) {
      var localization = _this.props.localization;
      var lowerCase = item.name.substr(0, 1).toLowerCase() + item.name.substr(1);
      var localized = localization[lowerCase];
      var visible = _this.props.cardVisibility[item.name];
      return React.createElement(MenuItem, {
        key: index,
        onClick: function onClick() {
          _this.props.setCardVisibility(item.name, !visible);
        }
      }, React.createElement(ListItemIcon, null, item.icon), React.createElement(ListItemText, null, localized ? localized.title : item.name), React.createElement(ListItemIcon, null, visible ? React.createElement(ToggleCheckBox, null) : React.createElement(ToggleCheckBoxOutlineBlank, null)));
    });

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "setExpandingEditorCard", function (isExpandingEditorCard) {
      return _this.setState({
        isExpandingEditorCard: isExpandingEditorCard
      });
    });

    return _this;
  }

  _createClass(Main, [{
    key: "componentDidMount",
    value: function componentDidMount() {
      var _this2 = this;

      // 定期的にスクリーンショットを撮る
      if (this.props.onThumbnailChange) {
        var globalEvent = this.state.globalEvent;
        var cache = new Set();
        globalEvent.on('message.capture', function (event) {
          var _ref = event.data || {},
              value = _ref.value;

          if (!cache.has(value)) {
            _this2.props.onThumbnailChange(value);

            cache.add(value);
          }
        });

        var screenShotLater =
        /*#__PURE__*/
        function () {
          var _ref2 = _asyncToGenerator(
          /*#__PURE__*/
          _regeneratorRuntime.mark(function _callee() {
            var request;
            return _regeneratorRuntime.wrap(function _callee$(_context) {
              while (1) {
                switch (_context.prev = _context.next) {
                  case 0:
                    _context.next = 2;
                    return new Promise(function (resolve) {
                      return window.setTimeout(resolve, 10 * 1000);
                    });

                  case 2:
                    request = {
                      query: 'capture',
                      type: 'image/jpeg',
                      requestedBy: 'auto' // 自動的にリクエストされることを表す

                    };
                    _context.next = 5;
                    return _this2.state.globalEvent.emitAsync('postMessage', request);

                  case 5:
                    screenShotLater();

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

          return function screenShotLater() {
            return _ref2.apply(this, arguments);
          };
        }();

        screenShotLater();
      } // iframe からのイベントを伝える


      this.state.globalEvent.on('message.dispatchOnMessage', function (event) {
        if (_this2.props.onMessage) {
          _this2.props.onMessage(_objectSpread({}, event));
        }
      });
      var feelesrc = this.loadConfig('feelesrc');
      this.props.setMuiTheme(feelesrc);
    }
  }, {
    key: "componentDidUpdate",
    value: function () {
      var _componentDidUpdate = _asyncToGenerator(
      /*#__PURE__*/
      _regeneratorRuntime.mark(function _callee2() {
        return _regeneratorRuntime.wrap(function _callee2$(_context2) {
          while (1) {
            switch (_context2.prev = _context2.next) {
              case 0:
                // mini の場合, openSidebar の props に追従 (stateless)
                if (this.props.mini && this.props.openSidebar !== this.state.openSidebar) {
                  this.setState({
                    openSidebar: this.props.openSidebar
                  });
                }

                if (this.state.reboot) {
                  this.setState({
                    reboot: false
                  });
                }

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

      function componentDidUpdate() {
        return _componentDidUpdate.apply(this, arguments);
      }

      return componentDidUpdate;
    }()
  }, {
    key: "setStatePromise",
    value: function () {
      var _setStatePromise = _asyncToGenerator(
      /*#__PURE__*/
      _regeneratorRuntime.mark(function _callee3(state) {
        var _this3 = this;

        return _regeneratorRuntime.wrap(function _callee3$(_context3) {
          while (1) {
            switch (_context3.prev = _context3.next) {
              case 0:
                return _context3.abrupt("return", new Promise(function (resolve) {
                  _this3.setState(state, resolve);
                }));

              case 1:
              case "end":
                return _context3.stop();
            }
          }
        }, _callee3, this);
      }));

      function setStatePromise(_x) {
        return _setStatePromise.apply(this, arguments);
      }

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

      if (this.componentWillMountCompat) {
        // render よりも先に呼ばれるライフサイクルメソッドがないので,
        // ここで呼んでいる. 一度しか呼ばれないように参照を null にする
        this.componentWillMountCompat();
        this.componentWillMountCompat = null;
        return null;
      }

      var _this$props = this.props,
          localization = _this$props.localization,
          mini = _this$props.mini;
      var commonProps = {
        localization: localization,
        getConfig: this.getConfig,
        loadConfig: this.loadConfig,
        showAll: this.state.showAll
      };
      return React.createElement("div", {
        className: cn.root
      }, mini ? null : React.createElement(Menu, _extends({}, commonProps, {
        toggleSidebar: this.toggleSidebar,
        setLocalization: this.props.setLocalization,
        openFileDialog: this.openFileDialog,
        setCardVisibility: this.setCardVisibility,
        showAll: this.state.showAll,
        toggleShowAll: this.toggleShowAll,
        globalEvent: this.state.globalEvent
      })), React.createElement(Drawer, {
        variant: "persistent",
        open: this.state.openSidebar,
        onClose: this.toggleSidebar,
        classes: cn.drawer
      }, this.props.mini ? null : React.createElement("div", {
        className: cn.alignRight
      }, React.createElement(IconButton, {
        onClick: this.toggleSidebar
      }, React.createElement(NavigationArrowBack, null))), icons.map(this.renderMenuItem)), React.createElement(CardContainer, _extends({}, commonProps, {
        cardProps: this.props.cardProps,
        cardVisibility: this.props.cardVisibility,
        setCardVisibility: this.props.setCardVisibility,
        setLocation: this.setLocation,
        openFileDialog: this.openFileDialog,
        reboot: this.state.reboot,
        href: this.state.href,
        monitorType: this.state.monitorType,
        toggleFullScreen: this.handleToggleFullScreen,
        togglePopout: this.handleTogglePopout,
        showNotice: this.handleShowNotice,
        ref: this.handleContainerRef,
        globalEvent: this.state.globalEvent,
        isExpandingEditorCard: this.state.isExpandingEditorCard,
        setExpandingEditorCard: this.setExpandingEditorCard
      })), React.createElement(FileDialog, {
        ref: this.handleFileDialog,
        localization: this.props.localization,
        globalEvent: this.state.globalEvent
      }), React.createElement(UserDefineStyle, null), React.createElement(CodemirrorStyle, null), React.createElement(Snackbar, _extends({
        open: this.state.notice !== null,
        message: "",
        autoHideDuration: 4000,
        onClose: function onClose() {
          return _this4.setState({
            notice: null
          });
        }
      }, this.state.notice)), React.createElement(MigrateAsset, null));
    }
  }, {
    key: "rootWidth",
    get: function get() {
      return parseInt(this.props.rootStyle.width, 10);
    }
  }, {
    key: "rootHeight",
    get: function get() {
      return parseInt(this.props.rootStyle.height, 10);
    }
  }]);

  return Main;
}(Component), _defineProperty(_class2, "propTypes", {
  theme: PropTypes.object.isRequired,
  cardProps: PropTypes.object.isRequired,
  cardVisibility: PropTypes.object.isRequired,
  setCardVisibility: PropTypes.func.isRequired,
  openSidebar: PropTypes.bool.isRequired,
  mini: PropTypes.bool.isRequired,
  rootStyle: PropTypes.object.isRequired,
  localization: PropTypes.object.isRequired,
  setLocalization: PropTypes.func.isRequired,
  setMuiTheme: PropTypes.func.isRequired,
  onChange: PropTypes.func,
  onMessage: PropTypes.func,
  onThumbnailChange: PropTypes.func,
  autoFullScreen: PropTypes.bool.isRequired,
  // Injected by withFiles (for JSX)
  files: PropTypes.array.isRequired,
  glob: PropTypes.func.isRequired,
  putFile: PropTypes.func.isRequired,
  putFiles: PropTypes.func.isRequired,
  deleteFiles: PropTypes.func.isRequired
}), _temp)) || _class) || _class);
export { Main as default };
var UserDefineStyle = withFiles({
  watch: 'feeles/codemirror.css'
})(function (props) {
  return props.files[0] ? React.createElement("style", null, props.files[0].text) : null;
});
var CodemirrorStyle = withTheme()(function (props) {
  return React.createElement("style", null, codemirrorStyle(props.theme));
});