'use strict';

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = undefined;

var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };

var _class;

var _circularJson = require('circular-json');

var _circularJson2 = _interopRequireDefault(_circularJson);

var _react = require('react');

var _react2 = _interopRequireDefault(_react);

var _autobindDecorator = require('autobind-decorator');

var _autobindDecorator2 = _interopRequireDefault(_autobindDecorator);

var _cheerio = require('cheerio');

var _cheerio2 = _interopRequireDefault(_cheerio);

var _express = require('express');

var _express2 = _interopRequireDefault(_express);

var _fsExtra = require('fs-extra');

var _fsExtra2 = _interopRequireDefault(_fsExtra);

var _ignoreWarnings = require('ignore-warnings');

var _ignoreWarnings2 = _interopRequireDefault(_ignoreWarnings);

var _index = require('@reactant/web-isomorphic/index.html');

var _index2 = _interopRequireDefault(_index);

var _path = require('path');

var _path2 = _interopRequireDefault(_path);

var _core = require('@reactant/core');

var _plugin = require('@reactant/core/plugin');

var _server = require('react-dom/server');

var _Reactant = require('./Reactant');

var _Reactant2 = _interopRequireDefault(_Reactant);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }

let ServerApp = (0, _autobindDecorator2.default)(_class = class ServerApp extends _core.ReactantApp {
  constructor(BaseRoot = _Reactant2.default, options = {}) {
    super(...arguments);
    var _options$app = options.app;
    const app = _options$app === undefined ? (0, _express2.default)() : _options$app;

    this.BaseRoot = BaseRoot;
    this.app = app;
    if (!_core.config.options.debug) {
      (0, _ignoreWarnings2.default)(_core.config.ignore.warnings || []);
      (0, _ignoreWarnings2.default)('error', _core.config.ignore.errors || []);
    }
  }

  handle(req, res, next) {
    var _this = this;

    return _asyncToGenerator(function* () {
      const paths = _core.config.paths;

      try {
        if (global.reactant) req.reactant = global.reactant;
        _core.log.silly('url:', req.url);
        req.props = _extends({}, _this.props);
        yield (0, _plugin.callLifecycle)('willRender', _this, { req, res });
        req.props.location = req.url;
        req.props.context = _extends({}, req.props.context, {
          location: req.props.location
        });
        const Root = yield _this.getRoot({ req, res });
        const props = req.props;

        if (req.reactant) req.reactant.context = props.context;
        const appHtml = (0, _server.renderToString)(_react2.default.createElement(Root, props));
        const $ = _cheerio2.default.load(_index2.default);
        $('title').text(_core.config.title);
        $('#app').append(appHtml);
        $('body').append(`<script src="${_core.assets.client.js}" defer${_core.config.environment === 'production' ? ' crossorigin' : ''}></script>`);
        req.$ = $;
        yield (0, _plugin.callLifecycle)('didRender', _this, { req, res });
        if (req.reactant) {
          _fsExtra2.default.mkdirsSync(paths.debug);
          _fsExtra2.default.writeFileSync(_path2.default.resolve(paths.debug, 'reactant.json'), _circularJson2.default.stringify(req.reactant, null, 2));
        }
        res.sent = true;
        return res.send(req.$.html());
      } catch (err) {
        return next(err);
      }
    })();
  }

  init() {
    var _this2 = this;

    return _asyncToGenerator(function* () {
      yield _core.ReactantApp.prototype.init.call(_this2);
      const paths = _core.config.paths;

      _this2.app.use(_express2.default.static(_path2.default.resolve(paths.dist, 'public')));
      _this2.app.get('/*', _this2.handle);
      return _this2;
    })();
  }
}) || _class;

exports.default = ServerApp;