"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.getCtx = getCtx;
exports.default = exports.addPrefix = void 0;

function _react() {
  const data = _interopRequireDefault(require("react"));

  _react = function _react() {
    return data;
  };

  return data;
}

function _assert() {
  const data = _interopRequireDefault(require("assert"));

  _assert = function _assert() {
    return data;
  };

  return data;
}

function _chalk() {
  const data = _interopRequireDefault(require("chalk"));

  _chalk = function _chalk() {
    return data;
  };

  return data;
}

function _fs() {
  const data = require("fs");

  _fs = function _fs() {
    return data;
  };

  return data;
}

function _path() {
  const data = require("path");

  _path = function _path() {
    return data;
  };

  return data;
}

function _ora() {
  const data = _interopRequireDefault(require("ora"));

  _ora = function _ora() {
    return data;
  };

  return data;
}

function _lodash() {
  const data = require("lodash");

  _lodash = function _lodash() {
    return data;
  };

  return data;
}

function _getnpmregistry() {
  const data = _interopRequireDefault(require("getnpmregistry"));

  _getnpmregistry = function _getnpmregistry() {
    return data;
  };

  return data;
}

function _clipboardy() {
  const data = _interopRequireDefault(require("clipboardy"));

  _clipboardy = function _clipboardy() {
    return data;
  };

  return data;
}

function _umiUtils() {
  const data = require("umi-utils");

  _umiUtils = function _umiUtils() {
    return data;
  };

  return data;
}

var _download = require("./download");

var _writeNewRoute = _interopRequireDefault(require("../../../utils/writeNewRoute"));

var _getBlockGenerator = require("./getBlockGenerator");

var _appendBlockToContainer = _interopRequireDefault(require("./appendBlockToContainer"));

var _util = require("./util");

var _installDependencies = _interopRequireDefault(require("./installDependencies"));

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

function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }

function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }

// fix demo => /demo
const addPrefix = path => {
  if (!/^\//.test(path)) {
    return `/${path}`;
  }

  return path;
};

exports.addPrefix = addPrefix;

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

function _getCtx() {
  _getCtx = _asyncToGenerator(function* (url, args = {}, api) {
    const debug = api.debug,
          config = api.config;
    debug(`get url ${url}`);
    const ctx = yield (0, _download.getParsedData)(url, _objectSpread({}, config.block || {}, {}, args));

    if (!ctx.isLocal) {
      const blocksTempPath = (0, _download.makeSureMaterialsTempPathExist)(args.dryRun);
      const templateTmpDirPath = (0, _path().join)(blocksTempPath, ctx.id);
      (0, _lodash().merge)(ctx, {
        routePath: args.routePath,
        sourcePath: (0, _path().join)(templateTmpDirPath, ctx.path),
        branch: args.branch || ctx.branch,
        templateTmpDirPath,
        blocksTempPath,
        repoExists: (0, _fs().existsSync)(templateTmpDirPath)
      });
    } else {
      (0, _lodash().merge)(ctx, {
        routePath: args.routePath,
        templateTmpDirPath: (0, _path().dirname)(url)
      });
    }

    return ctx;
  });
  return _getCtx.apply(this, arguments);
}

function add() {
  return _add.apply(this, arguments);
}

function _add() {
  _add = _asyncToGenerator(function* (args = {}, opts = {}, api) {
    const log = api.log,
          paths = api.paths,
          debug = api.debug,
          config = api.config,
          applyPlugins = api.applyPlugins,
          sendLog = api.sendLog;
    const blockConfig = config.block || {};
    const addLogs = [];

    const getSpinner = () => {
      const spinner = (0, _ora().default)();
      return _objectSpread({}, spinner, {
        succeed: info => spinner.succeed(info),
        start: info => {
          if (sendLog) {
            sendLog(info);
          }

          spinner.start(info);
          addLogs.push(info);
        },
        fail: info => spinner.fail(info),
        stopAndPersist: option => spinner.stopAndPersist(option)
      });
    };

    const spinner = getSpinner();

    if (!opts.remoteLog) {
      opts.remoteLog = () => {};
    } // 1. parse url and args


    spinner.start('😁  Parse url and args');
    const url = args.url;
    (0, _assert().default)(url, `run ${_chalk().default.cyan.underline('umi help block')} to checkout the usage`);
    const useYarn = (0, _fs().existsSync)((0, _path().join)(paths.cwd, 'yarn.lock'));
    const defaultNpmClient = blockConfig.npmClient || (useYarn ? 'yarn' : 'npm');
    debug(`defaultNpmClient: ${defaultNpmClient}`);
    debug(`args: ${JSON.stringify(args)}`); // get faster registry url

    const registryUrl = yield (0, _getnpmregistry().default)();
    const path = args.path,
          name = args.name,
          routePath = args.routePath,
          index = args.index,
          _args$npmClient = args.npmClient,
          npmClient = _args$npmClient === void 0 ? defaultNpmClient : _args$npmClient,
          dryRun = args.dryRun,
          skipDependencies = args.skipDependencies,
          skipModifyRoutes = args.skipModifyRoutes,
          isPage = args.page,
          isLayout = args.layout,
          _args$registry = args.registry,
          registry = _args$registry === void 0 ? registryUrl : _args$registry,
          js = args.js,
          _args$execution = args.execution,
          execution = _args$execution === void 0 ? 'shell' : _args$execution,
          uni18n = args.uni18n;
    const ctx = yield getCtx(url, args, api);
    spinner.succeed(); // 2. clone git repo

    if (!ctx.isLocal && !ctx.repoExists) {
      opts.remoteLog('Clone the git repo');
      yield (0, _util.gitClone)(ctx, spinner);
    } // 3. update git repo


    if (!ctx.isLocal && ctx.repoExists) {
      try {
        opts.remoteLog('Update the git repo');
        yield (0, _util.gitUpdate)(ctx, spinner);
      } catch (error) {
        log.info('发生错误，请尝试 `umi block clear`');
      }
    } // make sure sourcePath exists


    (0, _assert().default)((0, _fs().existsSync)(ctx.sourcePath), `${ctx.sourcePath} don't exists`); // get block's package.json

    const pkgPath = (0, _path().join)(ctx.sourcePath, 'package.json');

    if (!(0, _fs().existsSync)(pkgPath)) {
      throw new Error(`not find package.json in ${this.sourcePath}`);
    } else {
      // eslint-disable-next-line
      ctx.pkg = JSON.parse((0, _fs().readFileSync)(pkgPath, 'utf-8'));
    } // setup route path


    if (!path) {
      const blockName = (0, _getBlockGenerator.getNameFromPkg)(ctx.pkg);

      if (!blockName) {
        log.error("not find name in block's package.json");
        return;
      }

      ctx.filePath = `/${blockName}`;
      log.info(`Not find --path, use block name '${ctx.filePath}' as the target path.`);
    } else {
      ctx.filePath = (0, _umiUtils().winPath)(path);
    }

    ctx.filePath = addPrefix(ctx.filePath); // 如果 ctx.routePath 不存在，使用 filePath

    if (!routePath) {
      ctx.routePath = ctx.filePath;
    }

    ctx.routePath = addPrefix(ctx.routePath); // 4. install additional dependencies
    // check dependencies conflict and install dependencies
    // install

    opts.remoteLog('📦  Install extra dependencies');
    spinner.start('📦  install dependencies package');
    yield (0, _installDependencies.default)({
      npmClient,
      registry,
      applyPlugins,
      paths,
      debug,
      dryRun,
      spinner,
      skipDependencies
    }, ctx);
    spinner.succeed(); // 5. run generator

    opts.remoteLog('🔥  Generate files');
    spinner.start('🔥  Generate files');
    spinner.stopAndPersist();

    const BlockGenerator = require('./getBlockGenerator').default(api);

    let isPageBlock = ctx.pkg.blockConfig && ctx.pkg.blockConfig.specVersion === '0.1';

    if (isPage !== undefined) {
      // when user use `umi block add --page`
      isPageBlock = isPage;
    }

    debug(`isPageBlock: ${isPageBlock}`);
    const generator = new BlockGenerator(args._ ? args._.slice(2) : [], {
      sourcePath: ctx.sourcePath,
      path: ctx.filePath,
      routePath: ctx.routePath,
      blockName: name || (0, _getBlockGenerator.getNameFromPkg)(ctx.pkg),
      isPageBlock,
      dryRun,
      execution,
      env: {
        cwd: api.cwd
      },
      resolved: (0, _umiUtils().winPath)(__dirname)
    });

    try {
      yield generator.run();
    } catch (e) {
      spinner.fail();
      throw new Error(e);
    } // write dependencies


    if (ctx.pkg.blockConfig && ctx.pkg.blockConfig.dependencies) {
      const subBlocks = ctx.pkg.blockConfig.dependencies;

      try {
        yield Promise.all(subBlocks.map(block => {
          const subBlockPath = (0, _path().join)(ctx.templateTmpDirPath, block);
          debug(`subBlockPath: ${subBlockPath}`);
          return new BlockGenerator(args._.slice(2), {
            sourcePath: subBlockPath,
            path: isPageBlock ? generator.path : (0, _path().join)(generator.path, generator.blockFolderName),
            // eslint-disable-next-line
            blockName: (0, _getBlockGenerator.getNameFromPkg)(require((0, _path().join)(subBlockPath, 'package.json'))),
            isPageBlock: false,
            dryRun,
            env: {
              cwd: api.cwd
            },
            routes: api.config.routes,
            resolved: (0, _umiUtils().winPath)(__dirname)
          }).run();
        }));
      } catch (e) {
        spinner.fail();
        throw new Error(e);
      }
    }

    spinner.succeed(); // 调用 sylvanas 转化 ts

    if (js) {
      opts.remoteLog('🤔  TypeScript to JavaScript');
      spinner.start('🤔  TypeScript to JavaScript');

      require('./tsTojs').default(generator.blockFolderPath);

      spinner.succeed();
    }

    if (uni18n) {
      opts.remoteLog('🌎  remove i18n code');
      spinner.start('🌎  remove i18n code');

      require('./remove-locale').default(generator.blockFolderPath, uni18n);

      spinner.succeed();
    } // 6. write routes


    if (generator.needCreateNewRoute && api.config.routes && !skipModifyRoutes) {
      opts.remoteLog('⛱  Write route');
      spinner.start(`⛱  Write route ${generator.routePath} to ${api.service.userConfig.file}`); // 当前 _modifyBlockNewRouteConfig 只支持配置式路由
      // 未来可以做下自动写入注释配置，支持约定式路由

      const newRouteConfig = applyPlugins('_modifyBlockNewRouteConfig', {
        initialValue: _objectSpread({
          path: generator.routePath.toLowerCase(),
          component: `.${generator.path}`
        }, isLayout ? {
          routes: []
        } : {})
      });

      try {
        if (!dryRun) {
          (0, _writeNewRoute.default)(newRouteConfig, api.service.userConfig.file, paths.absSrcPath);
        }
      } catch (e) {
        spinner.fail();
        throw new Error(e);
      }

      spinner.succeed();
    } // 6. import block to container


    if (!generator.isPageBlock) {
      spinner.start(`Write block component ${generator.blockFolderName} import to ${generator.entryPath}`);

      try {
        (0, _appendBlockToContainer.default)({
          entryPath: generator.entryPath,
          blockFolderName: generator.blockFolderName,
          dryRun,
          index
        });
      } catch (e) {
        spinner.fail();
        throw new Error(e);
      }

      spinner.succeed();
    } // Final: show success message


    const _process$env = process.env,
          PORT = _process$env.PORT,
          BASE_PORT = _process$env.BASE_PORT; // Final: show success message

    const viewUrl = `http://localhost:${BASE_PORT || PORT || '8000'}${generator.path.toLowerCase()}`;

    try {
      _clipboardy().default.writeSync(viewUrl);

      log.success(`✨  Probable url ${_chalk().default.cyan(viewUrl)} ${_chalk().default.dim('(copied to clipboard)')} for view the block.`);
    } catch (e) {
      log.success(`✨  Probable url ${_chalk().default.cyan(viewUrl)} for view the block.`);
      log.error('copy to clipboard failed');
    } // return ctx and generator for test


    return {
      generator,
      ctx,
      logs: addLogs
    };
  });
  return _add.apply(this, arguments);
}

var _default = add;
exports.default = _default;