'use strict';

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

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 _react = require('react');

var _react2 = _interopRequireDefault(_react);

var _reactRedux = require('react-redux');

var _lodash = require('lodash');

var _lodash2 = _interopRequireDefault(_lodash);

var _path = require('path');

var _path2 = _interopRequireDefault(_path);

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

var _fsExtra2 = _interopRequireDefault(_fsExtra);

var _semver = require('semver');

var _semver2 = _interopRequireDefault(_semver);

var _glob = require('glob');

var _glob2 = _interopRequireDefault(_glob);

var _bluebird = require('bluebird');

var _bluebird2 = _interopRequireDefault(_bluebird);

var _reactFontawesome = require('react-fontawesome');

var _reactFontawesome2 = _interopRequireDefault(_reactFontawesome);

var _reactBootstrap = require('react-bootstrap');

var _selectors = require('views/utils/selectors');

var _pluginManagerUtils = require('views/services/plugin-manager-utils');

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

function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new _bluebird2.default(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 _bluebird2.default.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; }

const { APPDATA_PATH, config, proxy, i18n } = window;
const __ = i18n.setting.__.bind(i18n.setting);

const MIRROR_JSON_PATH = _path2.default.join(global.ROOT, 'assets', 'data', 'mirror.json');
const MIRRORS = require(MIRROR_JSON_PATH);

const PACKAGE_NAME = 'whocallsthefleet-database';
const DB_ROOT = _path2.default.join(APPDATA_PATH, 'wctf-db');
const DB_META_PATH = _path2.default.join(DB_ROOT, 'node_modules', PACKAGE_NAME, 'package.json');
const DB_FILE_PATH = _path2.default.join(DB_ROOT, 'node_modules', PACKAGE_NAME, 'db');

const DB_KEY = {
  arsenal_all: 'id',
  arsenal_weekday: 'weekday',
  item_type_collections: 'id',
  item_types: 'id',
  items: 'id',
  ship_classes: 'id',
  ship_type_collections: 'id',
  ship_types: 'id',
  ships: 'id',
  ship_namesuffix: 'id'
};

const fetchHeader = new Headers();
fetchHeader.set("Cache-Control", "max-age=0");
const defaultFetchOption = {
  method: "GET",
  cache: "default",
  headers: fetchHeader
};

function _ref() {
  const mirrorConf = config.get('packageManager.mirrorName');
  const useProxy = config.get("packageManager.proxy", false);
  const mirrorName = Object.keys(MIRRORS).includes(mirrorConf) ? mirrorConf : navigator.language === 'zh-CN' ? "taobao" : "npm";
  const registry = MIRRORS[mirrorName].server;
  const npmConfig = {
    registry,
    prefix: DB_ROOT
  };
  if (useProxy) {
    const { port } = proxy;
    npmConfig.http_proxy = `http://127.0.0.1:${port}`;
  }

  return npmConfig;
}

function _ref2(res) {
  return res.ok ? res.json() : undefined;
}

function _ref4(e) {
  return undefined;
}

function _ref7(content) {
  return JSON.parse(content);
}

function* _ref10() {
  const data = {};

  function* _ref8(dbPath) {
    const dbName = _path2.default.basename(dbPath, '.nedb');
    if (!(dbName in DB_KEY)) {
      return;
    }
    const buf = yield _fsExtra2.default.readFile(dbPath);
    const entries = buf.toString().split('\n').filter(Boolean);
    data[dbName] = (0, _lodash2.default)(entries).map(_ref7).keyBy(DB_KEY[dbName]).value();
  }

  function _ref9() {
    var _ref5 = _asyncToGenerator(_ref8);

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

  try {
    yield _bluebird2.default.map(_glob2.default.sync(`${DB_FILE_PATH}/*.nedb`), _ref9());
  } catch (e) {
    console.error(e.stack);
    return;
  }

  return data;
}

const WctfDB = (0, _reactRedux.connect)(state => ({
  version: (0, _lodash.get)((0, _selectors.wctfSelector)(state), 'version', '0.0.0')
}))(class WctfDB extends _react.Component {
  constructor(...args) {
    var _temp, _this;

    function* _ref6(force = false) {
      _this.setState({
        updating: true
      });

      let updateFlag = false;
      let meta;

      try {
        meta = yield _fsExtra2.default.readJSON(DB_META_PATH);
      } catch (e) {
        updateFlag = true;
      }

      if ((0, _lodash.get)(meta, 'version') !== _this.props.version) {
        updateFlag = true;
      }

      const npmConfig = _this.getNpmConfig();
      const data = yield yield fetch(`${npmConfig.registry}${PACKAGE_NAME}/latest`, defaultFetchOption).then(_ref2).catch(_ref4);
      if (!data || !data.version) {
        console.warn(`Can't find update info for wctf-db`);
      }

      updateFlag = updateFlag || _semver2.default.gt((0, _lodash.get)(data, 'version', '0.0.0'), _this.props.version);

      if (updateFlag) {
        try {
          yield (0, _pluginManagerUtils.installPackage)(PACKAGE_NAME, data.version, npmConfig);
          _this.loadDB();
          // eslint-disable-next-line no-console
          console.log(`wctf-db updated to ${data.version}`);
        } catch (e) {
          console.error(e);
        }
      } else {
        if (force) {
          _this.loadDB();
        }
        // eslint-disable-next-line no-console
        console.log(`No update for wctf-db, current: ${_this.props.version}, remote: ${data.version}`);
      }

      _this.setState({
        updating: false
      });
    }

    return _temp = _this = super(...args), this.state = {
      updating: false
    }, this.componentDidMount = _asyncToGenerator(function* () {
      yield _fsExtra2.default.ensureDir(DB_ROOT);
      yield _fsExtra2.default.ensureDir(_path2.default.join(DB_ROOT, 'node_modules'));
      _this.updateDB();
    }), this.loadDB = _asyncToGenerator(function* () {
      try {
        const meta = yield _fsExtra2.default.readJSON(DB_META_PATH);
        const data = yield _this.parseData();
        if (data) {
          _this.props.dispatch({
            type: '@@wctf-db-update',
            payload: _extends({
              version: meta.version,
              lastModified: +new Date() }, data)
          });
        }
      } catch (e) {
        console.error(e.stack);
      }
    }), this.getNpmConfig = _ref, this.updateDB = (() => {
      var _ref3 = _asyncToGenerator(_ref6);

      return function () {
        return _ref3.apply(this, arguments);
      };
    })(), this.parseData = _asyncToGenerator(_ref10), this.handleRefesh = () => this.updateDB(true), _temp;
  }

  // updateDB is similar to update a plugin
  // Steps:
  // - locally check if wctf-db should be updated or reinstalled
  //  + read package.json, if failure, should update
  //  + compare version package.json and props.version, if not equal, should update
  // - fetch remote data to get the latest version info, also checks update
  //  + get npm config data (mirror, proxy)
  //  + fetch latest release info json
  // - if should update, install the npm package
  // - load the new db if updated or forced to load
  // @params force: Boolean, reloads DB if no update available


  render() {
    const { updating } = this.state;
    return _react2.default.createElement(
      _react.Fragment,
      null,
      _react2.default.createElement(
        _reactBootstrap.Button,
        {
          bsSize: 'small',
          onClick: this.handleRefesh,
          disabled: updating,
          style: { marginRight: '1em' }
        },
        _react2.default.createElement(_reactFontawesome2.default, { name: 'refresh', spin: updating })
      ),
      __('Who Calls The Fleet Database'),
      ': ',
      _react2.default.createElement(
        _reactBootstrap.Label,
        { bsStyle: 'primary' },
        this.props.version
      )
    );
  }
});

exports.default = WctfDB;
module.exports = exports['default'];