import _extends from "@babel/runtime/helpers/extends";
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
import _regeneratorRuntime from "@babel/runtime/regenerator";
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
import _objectSpread from "@babel/runtime/helpers/objectSpread";
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, { PureComponent } from 'react';
import { withTheme } from '@material-ui/core/styles';
import PropTypes from 'prop-types';
import { style } from 'typestyle';
import Popout from '../../jsx/ReactPopout';
import Screen from './Screen';
import setSrcDoc from './setSrcDoc';
import registerHTML from './registerHTML';
import uniqueId from '../../utils/uniqueId';
import cloneError from '../../utils/cloneError';
import fetchPonyfill from 'fetch-ponyfill';
import ImmutableFile from '../../File/ImmutableFile';
import withFiles from '../../store/withFiles';
import normalize from '../../File/normalize';
var fetch = window.fetch || // for IE11
fetchPonyfill({
  // TODO: use babel-runtime to rewrite this into require("babel-runtime/core-js/promise")
  Promise: Promise
}).fetch;
var ConnectionTimeout = 1000;
var popoutTemplate = "<!DOCTYPE html>\n<html>\n    <head>\n        <meta charset=\"utf-8\">\n        <style media=\"screen\">\n        body {\n            margin: 0;\n        }\n        #popout-content-container {\n            width: 100vw;\n            height: 100vh;\n            display: flex;\n        }\n        </style>\n    </head>\n    <body>\n    </body>\n</html>\n";
var popoutURL = URL.createObjectURL(new Blob([popoutTemplate], {
  type: 'text/html'
}));
var SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
var webkitSpeechGrammarList = window.webkitSpeechGrammarList;

var getCn = function getCn(props) {
  return {
    root: style({
      width: '100%',
      height: '100%',
      left: 0,
      top: 0,
      boxSizing: 'border-box',
      opacity: 1,
      display: 'flex',
      justifyContent: 'center',
      alignItems: 'center',
      overflow: 'hidden',
      zIndex: 300,
      position: props.isFullScreen ? 'fixed' : 'relative',
      transition: props.theme.transitions.create()
    })
  };
};

var Monitor = (_dec = withTheme(), _dec2 = withFiles({}), _dec(_class = _dec2(_class = (_temp = _class2 =
/*#__PURE__*/
function (_PureComponent) {
  _inherits(Monitor, _PureComponent);

  function Monitor() {
    var _getPrototypeOf2;

    var _this;

    _classCallCheck(this, Monitor);

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

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

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "state", {
      error: null,
      port: null
    });

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "popoutOptions", {
      width: 300,
      height: 150,
      // means innerHeight of browser expecting Safari.
      left: 50,
      top: 50
    });

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "popoutClosed", false);

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "prevent", Promise.resolve());

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "handlePostMessage", function (value) {
      // emitAsync('postMessage', value)
      var port = _this.state.port;
      if (!port) return; // reply を receive するための id

      value = _objectSpread({
        id: uniqueId()
      }, value);
      return new Promise(function (resolve) {
        // catch reply message (once)
        var task = function task(event) {
          if (!event.data || event.data.id !== value.id) return;
          if (port) port.removeEventListener('message', task);
          resolve(event.data);
        };

        port.addEventListener('message', task); // post message to frame

        port.postMessage(value);
      });
    });

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "handleFetch",
    /*#__PURE__*/
    function () {
      var _ref2 = _asyncToGenerator(
      /*#__PURE__*/
      _regeneratorRuntime.mark(function _callee(_ref) {
        var data, reply, filePath, file, response, blob;
        return _regeneratorRuntime.wrap(function _callee$(_context) {
          while (1) {
            switch (_context.prev = _context.next) {
              case 0:
                data = _ref.data, reply = _ref.reply;
                console.warn("feeles.fetch is now deprecated because it cause CORS error. Use feeles.fetchText instead. file: ".concat(data.value));
                filePath = normalize(data.value);
                _context.prev = 3;
                file = _this.props.files.find(function (file) {
                  return file.name === filePath;
                });

                if (!file) {
                  _context.next = 9;
                  break;
                }

                reply({
                  value: file.blob
                });
                _context.next = 20;
                break;

              case 9:
                if (!(data.value.indexOf('http') === 0)) {
                  _context.next = 19;
                  break;
                }

                _context.next = 12;
                return fetch(data.value);

              case 12:
                response = _context.sent;
                _context.next = 15;
                return response.blob();

              case 15:
                blob = _context.sent;
                reply({
                  value: blob
                });
                _context.next = 20;
                break;

              case 19:
                reply({
                  error: true
                });

              case 20:
                _context.next = 25;
                break;

              case 22:
                _context.prev = 22;
                _context.t0 = _context["catch"](3);
                reply(cloneError(_context.t0));

              case 25:
              case "end":
                return _context.stop();
            }
          }
        }, _callee, this, [[3, 22]]);
      }));

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

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "handleResolve",
    /*#__PURE__*/
    function () {
      var _ref4 = _asyncToGenerator(
      /*#__PURE__*/
      _regeneratorRuntime.mark(function _callee2(_ref3) {
        var data, reply, moduleId, indexjs, file, response, text;
        return _regeneratorRuntime.wrap(function _callee2$(_context2) {
          while (1) {
            switch (_context2.prev = _context2.next) {
              case 0:
                data = _ref3.data, reply = _ref3.reply;
                moduleId = normalize(data.value);
                indexjs = normalize(data.value, 'index.js');

                if (!(!moduleId && !indexjs)) {
                  _context2.next = 5;
                  break;
                }

                throw new Error("Invalid module id: ".concat(data.value));

              case 5:
                file = _this.props.files.find(function (file) {
                  return file.moduleName === moduleId;
                }) || _this.props.files.find(function (file) {
                  return file.moduleName === indexjs;
                });

                if (!file) {
                  _context2.next = 22;
                  break;
                }

                _context2.prev = 7;
                _context2.t0 = reply;
                _context2.next = 11;
                return file.transpiled;

              case 11:
                _context2.t1 = _context2.sent;
                _context2.t2 = {
                  value: _context2.t1
                };
                (0, _context2.t0)(_context2.t2);
                _context2.next = 20;
                break;

              case 16:
                _context2.prev = 16;
                _context2.t3 = _context2["catch"](7);
                reply(cloneError(_context2.t3));

                _this.setState({
                  error: _context2.t3
                });

              case 20:
                _context2.next = 39;
                break;

              case 22:
                if (!(data.value.indexOf('http') === 0)) {
                  _context2.next = 38;
                  break;
                }

                _context2.prev = 23;
                _context2.next = 26;
                return fetch(data.value);

              case 26:
                response = _context2.sent;
                _context2.next = 29;
                return response.text();

              case 29:
                text = _context2.sent;
                reply({
                  value: text
                });
                _context2.next = 36;
                break;

              case 33:
                _context2.prev = 33;
                _context2.t4 = _context2["catch"](23);
                reply(cloneError(_context2.t4));

              case 36:
                _context2.next = 39;
                break;

              case 38:
                reply({
                  error: true
                });

              case 39:
              case "end":
                return _context2.stop();
            }
          }
        }, _callee2, this, [[7, 16], [23, 33]]);
      }));

      return function (_x2) {
        return _ref4.apply(this, arguments);
      };
    }());

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "handleFetchDataURL",
    /*#__PURE__*/
    function () {
      var _ref6 = _asyncToGenerator(
      /*#__PURE__*/
      _regeneratorRuntime.mark(function _callee3(_ref5) {
        var data, reply, response, blob, fileReader, filePath, file;
        return _regeneratorRuntime.wrap(function _callee3$(_context3) {
          while (1) {
            switch (_context3.prev = _context3.next) {
              case 0:
                data = _ref5.data, reply = _ref5.reply;

                if (!(data.value.indexOf('http') === 0)) {
                  _context3.next = 19;
                  break;
                }

                _context3.prev = 2;
                _context3.next = 5;
                return fetch(data.value);

              case 5:
                response = _context3.sent;
                _context3.next = 8;
                return response.blob();

              case 8:
                blob = _context3.sent;
                fileReader = new FileReader();

                fileReader.onload = function () {
                  reply({
                    value: fileReader.result
                  });
                };

                fileReader.readAsDataURL(blob);
                _context3.next = 17;
                break;

              case 14:
                _context3.prev = 14;
                _context3.t0 = _context3["catch"](2);
                reply(cloneError(_context3.t0));

              case 17:
                _context3.next = 30;
                break;

              case 19:
                filePath = normalize(data.value);
                file = _this.props.files.find(function (file) {
                  return file.name === filePath;
                });

                if (!file) {
                  _context3.next = 29;
                  break;
                }

                _context3.t1 = reply;
                _context3.next = 25;
                return file.toDataURL();

              case 25:
                _context3.t2 = _context3.sent;
                _context3.t3 = {
                  value: _context3.t2
                };
                (0, _context3.t1)(_context3.t3);
                return _context3.abrupt("return");

              case 29:
                reply({
                  error: true
                });

              case 30:
              case "end":
                return _context3.stop();
            }
          }
        }, _callee3, this, [[2, 14]]);
      }));

      return function (_x3) {
        return _ref6.apply(this, arguments);
      };
    }());

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "handleFetchText",
    /*#__PURE__*/
    function () {
      var _ref8 = _asyncToGenerator(
      /*#__PURE__*/
      _regeneratorRuntime.mark(function _callee4(_ref7) {
        var data, reply, response, text, filePath, file;
        return _regeneratorRuntime.wrap(function _callee4$(_context4) {
          while (1) {
            switch (_context4.prev = _context4.next) {
              case 0:
                data = _ref7.data, reply = _ref7.reply;

                if (!(data.value.indexOf('http') === 0)) {
                  _context4.next = 21;
                  break;
                }

                _context4.prev = 2;
                _context4.next = 5;
                return fetch(data.value);

              case 5:
                response = _context4.sent;

                if (!response.ok) {
                  _context4.next = 13;
                  break;
                }

                _context4.next = 9;
                return response.text();

              case 9:
                text = _context4.sent;
                reply({
                  value: text
                });
                _context4.next = 14;
                break;

              case 13:
                reply({
                  error: true
                });

              case 14:
                _context4.next = 19;
                break;

              case 16:
                _context4.prev = 16;
                _context4.t0 = _context4["catch"](2);
                reply(cloneError(_context4.t0));

              case 19:
                _context4.next = 27;
                break;

              case 21:
                filePath = normalize(data.value);
                file = _this.props.files.find(function (file) {
                  return file.name === filePath;
                });

                if (!file) {
                  _context4.next = 26;
                  break;
                }

                reply({
                  value: file.text
                });
                return _context4.abrupt("return");

              case 26:
                reply({
                  error: true
                });

              case 27:
              case "end":
                return _context4.stop();
            }
          }
        }, _callee4, this, [[2, 16]]);
      }));

      return function (_x4) {
        return _ref8.apply(this, arguments);
      };
    }());

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "handleFetchArrayBuffer",
    /*#__PURE__*/
    function () {
      var _ref10 = _asyncToGenerator(
      /*#__PURE__*/
      _regeneratorRuntime.mark(function _callee5(_ref9) {
        var data, reply, response, buffer, filePath, file, fileReader;
        return _regeneratorRuntime.wrap(function _callee5$(_context5) {
          while (1) {
            switch (_context5.prev = _context5.next) {
              case 0:
                data = _ref9.data, reply = _ref9.reply;

                if (!(data.value.indexOf('http') === 0)) {
                  _context5.next = 21;
                  break;
                }

                _context5.prev = 2;
                _context5.next = 5;
                return fetch(data.value);

              case 5:
                response = _context5.sent;

                if (!response.ok) {
                  _context5.next = 13;
                  break;
                }

                _context5.next = 9;
                return response.arrayBuffer();

              case 9:
                buffer = _context5.sent;
                reply({
                  value: buffer
                });
                _context5.next = 14;
                break;

              case 13:
                reply({
                  error: true
                });

              case 14:
                _context5.next = 19;
                break;

              case 16:
                _context5.prev = 16;
                _context5.t0 = _context5["catch"](2);
                reply(cloneError(_context5.t0));

              case 19:
                _context5.next = 29;
                break;

              case 21:
                filePath = normalize(data.value);
                file = _this.props.files.find(function (file) {
                  return file.name === filePath;
                });

                if (!(file && file.blob)) {
                  _context5.next = 28;
                  break;
                }

                fileReader = new FileReader();

                fileReader.onload = function () {
                  reply({
                    value: fileReader.result
                  });
                };

                fileReader.readAsArrayBuffer(file.blob);
                return _context5.abrupt("return");

              case 28:
                reply({
                  error: true
                });

              case 29:
              case "end":
                return _context5.stop();
            }
          }
        }, _callee5, this, [[2, 16]]);
      }));

      return function (_x5) {
        return _ref10.apply(this, arguments);
      };
    }());

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "handleSaveAs",
    /*#__PURE__*/
    function () {
      var _ref12 = _asyncToGenerator(
      /*#__PURE__*/
      _regeneratorRuntime.mark(function _callee6(_ref11) {
        var data, reply, _data$value, blob, name, file;

        return _regeneratorRuntime.wrap(function _callee6$(_context6) {
          while (1) {
            switch (_context6.prev = _context6.next) {
              case 0:
                data = _ref11.data, reply = _ref11.reply;
                _data$value = _slicedToArray(data.value, 2), blob = _data$value[0], name = _data$value[1];
                blob.name = name;
                _context6.next = 5;
                return ImmutableFile.fromFile(blob);

              case 5:
                file = _context6.sent;

                _this.props.putFile(file);

                reply();

              case 8:
              case "end":
                return _context6.stop();
            }
          }
        }, _callee6, this);
      }));

      return function (_x6) {
        return _ref12.apply(this, arguments);
      };
    }());

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "handleReload", function () {
      _this.props.setLocation();
    });

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "handleReplace", function (_ref13) {
      var data = _ref13.data;
      location.hash = data.value.replace(/^\/*/, '/');
    });

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "handleError", function (_ref14) {
      var data = _ref14.data;

      if (!_this.state.error) {
        var error = new Error(data.value.message || '');

        var _arr = Object.keys(data.value);

        for (var _i = 0; _i < _arr.length; _i++) {
          var key = _arr[_i];
          error[key] = data.value[key];
        }

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

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "handleIpcRenderer", function (_ref15) {
      var data = _ref15.data;

      if (window.ipcRenderer) {
        var _window$ipcRenderer;

        (_window$ipcRenderer = window.ipcRenderer).sendToHost.apply(_window$ipcRenderer, _toConsumableArray(Object.values(data.value)));
      } else {
        console.warn('window.ipcRenderer is not defined');
      }
    });

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

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "handleSetTimeout", function (_ref16) {
      var data = _ref16.data,
          reply = _ref16.reply;
      var _data$value2 = data.value,
          timeoutId = _data$value2.timeoutId,
          delay = _data$value2.delay;

      _this.setTimeoutId.set(timeoutId, setTimeout(reply, delay));
    });

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "handleClearTimeout", function (_ref17) {
      var data = _ref17.data;
      clearInterval(_this.setTimeoutId.get(data.value.timeoutId));
    });

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

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "handleSetInterval", function (_ref18) {
      var data = _ref18.data,
          reply = _ref18.reply;
      var _data$value3 = data.value,
          intervalId = _data$value3.intervalId,
          delay = _data$value3.delay;

      _this.setIntervalId.set(intervalId, setInterval(reply, delay));
    });

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "handleClearInterval", function (_ref19) {
      var data = _ref19.data;
      clearInterval(_this.setIntervalId.get(data.value.intervalId));
    });

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "handleOpenWindow", function (_ref20) {
      var value = _ref20.data.value;
      // value.url が相対パスかどうかを調べる
      var a = document.createElement('a');
      a.href = value.url;

      if (a.host === location.host) {
        window.open(value.url, value.target, value.features, value.replace);
      } else {
        throw new Error("Cannot open ".concat(value.url));
      }
    });

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "handleSpeechRecognition", function (_ref21) {
      var data = _ref21.data,
          reply = _ref21.reply;
      var recognition = new SpeechRecognition();
      var _arr2 = ['lang', 'continuous', 'interimResults', 'maxAlternatives', 'serviceURI'];

      for (var _i2 = 0; _i2 < _arr2.length; _i2++) {
        var prop = _arr2[_i2];

        if (data.value[prop] !== undefined) {
          recognition[prop] = data.value[prop];
        }
      }

      if (Array.isArray(data.value.grammars)) {
        recognition.grammars = new webkitSpeechGrammarList();
        var _iteratorNormalCompletion = true;
        var _didIteratorError = false;
        var _iteratorError = undefined;

        try {
          for (var _iterator = data.value.grammars[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
            var _step$value = _step.value,
                src = _step$value.src,
                weight = _step$value.weight;
            recognition.grammars.addFromString(src, weight);
          }
        } catch (err) {
          _didIteratorError = true;
          _iteratorError = err;
        } finally {
          try {
            if (!_iteratorNormalCompletion && _iterator.return != null) {
              _iterator.return();
            }
          } finally {
            if (_didIteratorError) {
              throw _iteratorError;
            }
          }
        }
      }

      recognition.onresult = function (event) {
        var results = [];
        var _iteratorNormalCompletion2 = true;
        var _didIteratorError2 = false;
        var _iteratorError2 = undefined;

        try {
          for (var _iterator2 = event.results[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
            var items = _step2.value;
            var result = [];
            result.isFinal = items.isFinal;
            var _iteratorNormalCompletion3 = true;
            var _didIteratorError3 = false;
            var _iteratorError3 = undefined;

            try {
              for (var _iterator3 = items[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
                var _step3$value = _step3.value,
                    confidence = _step3$value.confidence,
                    transcript = _step3$value.transcript;
                result.push({
                  confidence: confidence,
                  transcript: transcript
                });
              }
            } catch (err) {
              _didIteratorError3 = true;
              _iteratorError3 = err;
            } finally {
              try {
                if (!_iteratorNormalCompletion3 && _iterator3.return != null) {
                  _iterator3.return();
                }
              } finally {
                if (_didIteratorError3) {
                  throw _iteratorError3;
                }
              }
            }

            results.push(result);
          }
        } catch (err) {
          _didIteratorError2 = true;
          _iteratorError2 = err;
        } finally {
          try {
            if (!_iteratorNormalCompletion2 && _iterator2.return != null) {
              _iterator2.return();
            }
          } finally {
            if (_didIteratorError2) {
              throw _iteratorError2;
            }
          }
        }

        reply({
          type: 'result',
          event: {
            results: results
          }
        });
      };

      recognition.onerror = function (event) {
        reply({
          type: 'error',
          event: {
            error: cloneError(event.error)
          }
        });
      };

      ['audioend', 'audiostart', 'end', 'nomatch', 'soundend', 'soundstart', 'speechend', 'speechstart', 'start'].forEach(function (type) {
        recognition["on".concat(type)] = function () {
          reply({
            type: type
          });
        };
      });
      recognition.start();
    });

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "handlePopoutOpen", function () {
      for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
        args[_key2] = arguments[_key2];
      }

      _this.parent = window.open.apply(window, args);

      if (_this.parent) {
        _this.parent.addEventListener('load', function () {
          var out = _this.popoutOptions.height !== _this.parent.innerHeight;

          _this.parent.addEventListener('resize', function () {
            _this.popoutOptions = Object.assign({}, _this.popoutOptions, {
              width: _this.parent.innerWidth,
              height: out ? _this.parent.outerHeight : _this.parent.innerHeight
            });
          });

          var popoutMove = setInterval(function () {
            if (_this.parent.screenX === _this.popoutOptions.left && _this.parent.screenY === _this.popoutOptions.top) {
              return;
            }

            _this.popoutOptions = Object.assign({}, _this.popoutOptions, {
              left: _this.parent.screenX,
              top: _this.parent.screenY
            });
          }, 100);

          _this.parent.addEventListener('beforeunload', function () {
            clearInterval(popoutMove);
          });
        });
      }

      return _this.parent;
    });

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "handlePopoutClose", function () {
      if (_this.props.isPopout && !_this.props.reboot) {
        _this.props.togglePopout();
      }
    });

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "handleFrame", function (ref) {
      if (!_this.props.isPopout) {
        _this.inlineFrame = ref;
      } else {
        _this.popoutFrame = ref;
      }
    });

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "handleHashChanged", function () {
      if (/^#\//.test(location.hash)) {
        var href = location.hash.substr(2);

        _this.props.setLocation(href);
      }
    });

    return _this;
  }

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

      if (window.ipcRenderer) {
        this._emit = window.ipcRenderer.emit; // あとで戻せるようオリジナルを保持

        var self = this;

        window.ipcRenderer.emit = function () {
          for (var _len3 = arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {
            args[_key3] = arguments[_key3];
          }

          // ipcRenderer.emit をオーバーライドし, 全ての postMessage で送る
          if (self.state && self.state.port) {
            self.state.port.postMessage({
              query: 'ipcRenderer.emit',
              value: JSON.parse(JSON.stringify(args))
            });
          }

          _this2._emit.apply(_this2, args);
        };
      } // feeles.github.io/sample/#/path/to/index.html


      window.addEventListener('hashchange', this.handleHashChanged);

      if (/^#\//.test(location.hash)) {
        this.handleHashChanged();
      } else {
        // default href で起動
        this.props.setLocation();
      }

      var globalEvent = this.props.globalEvent;
      var on = globalEvent.on.bind(globalEvent);
      on('postMessage', this.handlePostMessage);
      on('message.fetch', this.handleFetch);
      on('message.resolve', this.handleResolve);
      on('message.fetchDataURL', this.handleFetchDataURL);
      on('message.fetchText', this.handleFetchText);
      on('message.fetchArrayBuffer', this.handleFetchArrayBuffer);
      on('message.saveAs', this.handleSaveAs);
      on('message.reload', this.handleReload);
      on('message.replace', this.handleReplace);
      on('message.error', this.handleError);
      on('message.ipcRenderer.*', this.handleIpcRenderer);
      on('message.api.SpeechRecognition', this.handleSpeechRecognition);
      on('message.setTimeout', this.handleSetTimeout);
      on('message.clearTimeout', this.handleClearTimeout);
      on('message.setInterval', this.handleSetInterval);
      on('message.clearInterval', this.handleClearInterval);
      on('message.openWindow', this.handleOpenWindow);
    }
  }, {
    key: "componentDidUpdate",
    value: function componentDidUpdate(prevProps) {
      var _this3 = this;

      if (prevProps.reboot && !this.props.reboot) {
        if (this.props.isPopout || this.popoutClosed) {
          // react-popoutがpopoutWindowにDOMをrenderした後でstartする必要がある
          // renderを補足するのは難しい&updateの度に何度もrenderされる=>delayを入れる
          setTimeout(function () {
            return _this3.start();
          }, 500);
          this.popoutClosed = false;
        } else {
          this.start();
        }
      }

      if (prevProps.isPopout && !this.props.isPopout) {
        this.popoutClosed = true; // Use delay
      }

      if (!prevProps.isFullScreen && this.props.isFullScreen) {
        // フルスクリーン時にフォーカスを iframe に与える
        if (this.iframe) {
          this.iframe.contentWindow.focus();
        }
      }
    }
  }, {
    key: "componentWillUnmount",
    value: function componentWillUnmount() {
      window.removeEventListener('hashchange', this.handleHashChanged);

      if (window.ipcRenderer) {
        // オリジナルの参照を戻す. Monitor が複数 mount されることはない(はず)
        window.ipcRenderer.emit = this._emit;
      }
    }
  }, {
    key: "start",
    value: function () {
      var _start = _asyncToGenerator(
      /*#__PURE__*/
      _regeneratorRuntime.mark(function _callee7() {
        var _this4 = this;

        var _prevent;

        return _regeneratorRuntime.wrap(function _callee7$(_context7) {
          while (1) {
            switch (_context7.prev = _context7.next) {
              case 0:
                _prevent = this.prevent;
                this.prevent = _prevent.then(function () {
                  return _this4.startProcess();
                }).catch(function (error) {
                  if (error) {
                    _this4.setState({
                      error: error
                    });
                  } else if (_this4.props.isPopout) {
                    _this4.start();
                  }
                });
                _context7.next = 4;
                return _prevent;

              case 4:
                this.setState({
                  error: null,
                  port: null
                });

              case 5:
              case "end":
                return _context7.stop();
            }
          }
        }, _callee7, this);
      }));

      function start() {
        return _start.apply(this, arguments);
      }

      return start;
    }()
  }, {
    key: "startProcess",
    value: function () {
      var _startProcess = _asyncToGenerator(
      /*#__PURE__*/
      _regeneratorRuntime.mark(function _callee8() {
        var _this5 = this;

        var htmlFile, html, tryLoading, _ref22, port1, port2;

        return _regeneratorRuntime.wrap(function _callee8$(_context8) {
          while (1) {
            switch (_context8.prev = _context8.next) {
              case 0:
                htmlFile = this.props.files.find(function (file) {
                  return file.name === normalize(_this5.props.href);
                }) || notFound();
                _context8.next = 3;
                return registerHTML(htmlFile.text, this.props.files);

              case 3:
                html = _context8.sent;

                tryLoading = function tryLoading() {
                  return new Promise(function (resolve, reject) {
                    // iframe.srcdoc, onload => resolve
                    setSrcDoc(_this5.iframe, html, resolve); // Connection timeouted, then retry

                    setTimeout(reject, ConnectionTimeout);
                  }).catch(function () {
                    return tryLoading();
                  });
                };

                _context8.next = 7;
                return tryLoading();

              case 7:
                _ref22 = new MessageChannel(), port1 = _ref22.port1, port2 = _ref22.port2;
                port1.addEventListener('message', function (event) {
                  var reply = function reply(params) {
                    params = _objectSpread({
                      id: event.data.id
                    }, params || {});
                    port1.postMessage(params);
                  };

                  var type = event.type,
                      data = event.data;
                  var name = data.query ? "message.".concat(data.query) : 'message';

                  _this5.props.globalEvent.emit(name, {
                    type: type,
                    data: data,
                    reply: reply
                  });
                });
                port1.start();
                this.setState({
                  port: port1
                });
                this.iframe.contentWindow.postMessage({
                  env: {}
                }, '*', [port2]);

              case 12:
              case "end":
                return _context8.stop();
            }
          }
        }, _callee8, this);
      }));

      function startProcess() {
        return _startProcess.apply(this, arguments);
      }

      return startProcess;
    }()
  }, {
    key: "render",
    value: function render() {
      var dcn = getCn(this.props);
      var error = this.state.error;
      var _this$props = this.props,
          isPopout = _this$props.isPopout,
          reboot = _this$props.reboot,
          isFullScreen = _this$props.isFullScreen;
      var extraProps = {};

      if (isPopout || isFullScreen) {
        // バーがないのでリロードボタンを出す
        extraProps.setLocation = this.props.setLocation;
      }

      if (isFullScreen) {
        // フルスクリーン中に解除する
        extraProps.toggleFullScreen = this.props.toggleFullScreen;
      }

      var popout = isPopout && !reboot ? React.createElement(Popout, {
        url: popoutURL,
        title: "app",
        options: this.popoutOptions,
        window: {
          open: this.handlePopoutOpen,
          addEventListener: window.addEventListener.bind(window),
          removeEventListener: window.removeEventListener.bind(window)
        },
        onClosing: this.handlePopoutClose
      }, React.createElement(Screen, _extends({
        display: true,
        frameRef: this.handleFrame,
        reboot: reboot,
        error: error,
        width: this.props.frameWidth,
        height: this.props.frameHeight
      }, extraProps))) : null;
      return React.createElement("div", {
        className: dcn.root
      }, popout, React.createElement(Screen, _extends({
        animation: true,
        display: !isPopout,
        frameRef: this.handleFrame,
        reboot: reboot,
        error: error,
        width: this.props.frameWidth,
        height: this.props.frameHeight,
        isFullScreen: this.props.isFullScreen
      }, extraProps)));
    }
  }, {
    key: "iframe",
    get: function get() {
      return this.props.isPopout ? this.popoutFrame : this.inlineFrame;
    }
  }]);

  return Monitor;
}(PureComponent), _defineProperty(_class2, "propTypes", {
  theme: PropTypes.object.isRequired,
  isPopout: PropTypes.bool.isRequired,
  isFullScreen: PropTypes.bool.isRequired,
  reboot: PropTypes.bool.isRequired,
  href: PropTypes.string.isRequired,
  togglePopout: PropTypes.func.isRequired,
  toggleFullScreen: PropTypes.func.isRequired,
  localization: PropTypes.object.isRequired,
  setLocation: PropTypes.func.isRequired,
  frameWidth: PropTypes.number.isRequired,
  frameHeight: PropTypes.number.isRequired,
  globalEvent: PropTypes.object.isRequired,
  // Injected by withFiles (for JSX)
  files: PropTypes.array.isRequired,
  putFile: PropTypes.func.isRequired
}), _temp)) || _class) || _class);
export { Monitor as default };

function notFound() {
  var text = "<!DOCTYPE html>\n<html>\n    <head>\n        <meta charset=\"utf-8\">\n        <title>404 Not Found</title>\n    </head>\n    <body style=\"background-color: white;\">\n      File Not Found\n    </body>\n</html>";
  return new ImmutableFile({
    name: '404.html',
    type: 'text/html',
    text: text
  });
}