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, { Component } from 'react';
import PropTypes from 'prop-types';
import { style } from 'typestyle';
import moment from 'moment';
import HTML5Backend from 'react-dnd-html5-backend';
import TouchBackend from 'react-dnd-touch-backend';
import URLSearchParams from 'url-search-params';
import { DragDropContext } from 'react-dnd';
import { MuiThemeProvider } from '@material-ui/core/styles';
import { mapValues } from 'lodash';
import getLocalization from '../localization/';
import getCustomTheme from '../js/getCustomTheme';
import Main from './Main';
import ErrorBoundary from './ErrorBoundary';
import MaterialUIJssProvider from './MaterialUIJssProvider';
import ImmutableFile from '../File/ImmutableFile';
import fetchPonyfill from 'fetch-ponyfill';
import { CircularProgress } from '@material-ui/core';
import withFiles from '../store/withFiles';
import { connect } from 'react-redux';
import * as asset from '../store/asset';
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 cn = {
  root: style({
    display: 'flex',
    width: '100%',
    height: '100%',
    flexDirection: 'column',
    justifyContent: 'center',
    alignItems: 'center'
  }),
  errorText: style({
    color: 'red'
  })
};
var RootComponent = (_dec = withFiles({}), _dec2 = connect(null, asset.actions), _dec(_class = _dec2(_class = (_temp = _class2 =
/*#__PURE__*/
function (_Component) {
  _inherits(RootComponent, _Component);

  function RootComponent() {
    var _getPrototypeOf2;

    var _this;

    _classCallCheck(this, RootComponent);

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

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

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "state", {
      cardProps: null,
      cardVisibility: null,
      localization: null,
      muiTheme: getCustomTheme({}),
      retryCount: 0,
      errorText: null
    });

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "setCardVisibility", function (name) {
      var visible = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
      var cardProps = _this.state.cardProps;
      if (!cardProps) return;

      if (!cardProps[name]) {
        throw new TypeError("Property \"".concat(name, "\" is not found in cardProps: ").concat(JSON.stringify(cardProps)));
      }

      _this.setState({
        cardVisibility: _objectSpread({}, _this.state.cardVisibility, _defineProperty({}, name, visible))
      });
    });

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "launchFromURL",
    /*#__PURE__*/
    function () {
      var _ref = _asyncToGenerator(
      /*#__PURE__*/
      _regeneratorRuntime.mark(function _callee(url) {
        var text, response, delay, seeds, errorText, _errorText, files;

        return _regeneratorRuntime.wrap(function _callee$(_context) {
          while (1) {
            switch (_context.prev = _context.next) {
              case 0:
                _context.prev = 0;
                _context.next = 3;
                return fetch(url);

              case 3:
                response = _context.sent;
                _context.next = 6;
                return response.text();

              case 6:
                text = _context.sent;
                _context.next = 14;
                break;

              case 9:
                _context.prev = 9;
                _context.t0 = _context["catch"](0);

                _this.setState(function (prevState) {
                  return {
                    retryCount: prevState.retryCount + 1,
                    errorText: _context.t0.message
                  };
                }); // Auto retry


                delay = Math.min(64, Math.pow(2, _this.state.retryCount + 1));
                return _context.abrupt("return", new Promise(function (resolve, reject) {
                  window.setTimeout(function () {
                    _this.launchFromURL(url).then(resolve, reject);
                  }, delay * 1000);
                }));

              case 14:
                seeds = [];
                _context.prev = 15;
                seeds = JSON.parse(text);
                _context.next = 26;
                break;

              case 19:
                _context.prev = 19;
                _context.t1 = _context["catch"](15);
                console.log(text);
                errorText = "".concat(url, " is not valid JSON. Check the text in console.");
                console.info(errorText);

                _this.setState({
                  errorText: errorText
                });

                return _context.abrupt("return");

              case 26:
                if (Array.isArray(seeds)) {
                  _context.next = 32;
                  break;
                }

                console.log(seeds);
                _errorText = 'Source JSON file must be an array. Check the value in cosole.';
                console.info(_errorText);

                _this.setState({
                  errorText: _errorText
                });

                return _context.abrupt("return");

              case 32:
                files = ImmutableFile.fromSeeds(seeds);

                _this.props.putFiles(files);

              case 34:
              case "end":
                return _context.stop();
            }
          }
        }, _callee, this, [[0, 9], [15, 19]]);
      }));

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

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "setLocalization", function (langs) {
      langs = [].concat(langs);
      var localization = getLocalization(langs);

      if (localization) {
        _this.setState({
          localization: localization
        });

        moment.locale(localization.ll_CC);
      } else {
        throw new TypeError("setLocalization: Cannot parse ".concat(langs.join()));
      }
    });

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "setMuiTheme", function (theme) {
      return _this.setState({
        muiTheme: getCustomTheme(theme)
      });
    });

    _defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), "renderLoading", function () {
      var _this$state = _this.state,
          errorText = _this$state.errorText,
          retryCount = _this$state.retryCount;
      return React.createElement("div", {
        className: cn.root
      }, errorText && React.createElement("span", {
        className: cn.errorText
      }, errorText), retryCount > 0 ? React.createElement("div", null, Math.pow(2, retryCount), "\u79D2\u5F8C\u306B\u3082\u3046\u4E00\u5EA6\u63A5\u7D9A\u3057\u307E\u3059...") : null, React.createElement(CircularProgress, {
        size: 60,
        color: "primary"
      }));
    });

    return _this;
  }

  _createClass(RootComponent, [{
    key: "componentDidMount",
    value: function componentDidMount() {
      var seeds = this.props.seeds;
      this.setLocalization(this.langs);

      if (!this.props.asset) {
        // asset が与えられなかった => compatible mode でアセットを生成する
        this.props.setCompatibleMode(true);
      }

      this.updateStore({}, this.props);

      if (Array.isArray(seeds)) {
        this.props.putFiles(ImmutableFile.fromSeeds(seeds));
      } else if (typeof this.props.jsonURL === 'string') {
        this.launchFromURL(this.props.jsonURL);
      } else {
        throw new Error('No files/url given. Set seeds:Array or jsonURL:string');
      }
    }
  }, {
    key: "componentDidUpdate",
    value: function componentDidUpdate(prevProps) {
      // ファイル変更検知
      if (this.props.onChange && prevProps.files !== this.props.files) {
        this.props.onChange({
          files: this.props.files
        });
      }

      this.updateStore(prevProps, this.props);
    }
  }, {
    key: "updateStore",
    value: function updateStore(prevProps, nextProps) {
      if (prevProps.asset !== nextProps.asset && nextProps.asset) {
        this.props.setPackage(nextProps.asset);
      }

      if (prevProps.plan !== nextProps.plan && nextProps.plan) {
        this.props.setPlan(nextProps.plan);
      }
    }
  }, {
    key: "render",
    value: function render() {
      var _this$props = this.props,
          rootElement = _this$props.rootElement,
          files = _this$props.files;
      return React.createElement(ErrorBoundary, null, React.createElement(MaterialUIJssProvider, null, React.createElement(MuiThemeProvider, {
        theme: this.state.muiTheme
      }, files.length <= 0 || !this.state.cardProps ? this.renderLoading() : React.createElement(Main, {
        cardProps: this.state.cardProps,
        cardVisibility: this.state.cardVisibility,
        setCardVisibility: this.setCardVisibility,
        openSidebar: this.props.openSidebar,
        mini: this.props.mini,
        rootElement: rootElement,
        rootStyle: getComputedStyle(rootElement),
        localization: this.localization,
        setLocalization: this.setLocalization,
        muiTheme: this.state.muiTheme,
        setMuiTheme: this.setMuiTheme,
        onChange: this.props.onChange,
        onMessage: this.props.onMessage,
        onThumbnailChange: this.props.onThumbnailChange,
        autoFullScreen: this.props.autoFullScreen
      }))));
    }
  }, {
    key: "langs",
    get: function get() {
      return [].concat(new URLSearchParams(location.search).getAll('lang')) // ?lang=ll_CC
      .concat(navigator.languages || navigator.language); // browser settings
    }
  }, {
    key: "localization",
    get: function get() {
      return this.state.localization || getLocalization(this.langs);
    }
  }], [{
    key: "getDerivedStateFromProps",
    value: function getDerivedStateFromProps(props, state) {
      if (!state.cardProps && props.files.length > 0) {
        // feeles/card.json を探す
        var card = props.files.find(function (file) {
          return file.name === 'feeles/card.json';
        });

        if (!card) {
          throw new Error('Missing feeles/card.json');
        }

        try {
          var cardProps = JSON.parse(card.text);
          return {
            cardProps: cardProps,
            cardVisibility: mapValues(cardProps, 'visible')
          };
        } catch (error) {
          throw new Error("Invalid feeles/card.json: ".concat(card.text));
        }
      }

      return null;
    }
  }]);

  return RootComponent;
}(Component), _defineProperty(_class2, "propTypes", {
  // Toggle left menubar
  openSidebar: PropTypes.bool,
  // Disappear top navbar
  mini: PropTypes.bool,
  // Root element
  rootElement: PropTypes.object.isRequired,
  // Array of seed object
  seeds: PropTypes.array,
  // An URL string as JSON file provided
  jsonURL: PropTypes.string,
  // Handle file change
  onChange: PropTypes.func,
  // Handle message from iframe
  onMessage: PropTypes.func,
  // Handle screenshot image change
  onThumbnailChange: PropTypes.func,
  // Asset definition as a module
  asset: PropTypes.object,
  // 'free' | 'paid' | undefined
  plan: PropTypes.string,
  // Full screen as default
  autoFullScreen: PropTypes.bool.isRequired,
  // Injected by connect
  setPackage: PropTypes.func.isRequired,
  setPlan: PropTypes.func.isRequired,
  setCompatibleMode: PropTypes.func.isRequired,
  // Injected by withFiles (for JSX)
  files: PropTypes.array.isRequired,
  putFile: PropTypes.func.isRequired,
  putFiles: PropTypes.func.isRequired
}), _defineProperty(_class2, "defaultProps", {
  openSidebar: false,
  mini: false,
  autoFullScreen: false
}), _temp)) || _class) || _class);
var dndBackend = 'ontouchend' in document ? TouchBackend : HTML5Backend;
export default DragDropContext(dndBackend)(RootComponent);