import { logger } from '../utils/logger';
import { PluginInfo } from './plugin';
import config from '../config';
import { Git } from '../install/git';
import { addEnvPath } from '../utils/path';
import Linker from '../linker';
import { spawn } from 'child_process';
import * as path from "path";
import fs from '../fs';

// 标准输出类型
export interface output {
  stdout: string;
  stderr: string;
  code: number;
}

async function installRuntime(git: Git) {
  if (!config.runtimePlugin) {
    return;
  }
  const pluginInfo = await git.install(config.runtimePlugin);
  const linker = new Linker('');
  const protocol = await pluginInfo.getProtocol();
  return linker.registerCustom(config.binPath, protocol.command.getCommands(), config.runtimePlugin);
}

// 安装插件
export async function install(plugin: string, link?: boolean): Promise<PluginInfo> {
  const git = new Git();
  const [pi] = await Promise.all([
    git.install(plugin),
    installRuntime(git),
  ]);
  if (link) {
    const linker = new Linker(path.join(config.binPath, config.runtimePlugin));
    // 要求运行时支持 run 子命令
    await linker.register(config.binPath, `run ${pi.path}`, pi.name);
  }
  return pi;
}

// 卸载插件
export async function uninstall(plugin: string): Promise<PluginInfo> {
  const git = new Git();
  const pi = await git.uninstall(plugin);
  const command = path.join(config.binPath, pi.name);
  try {
    await fs.unlink(command);
  } catch{}
  return pi;
}

// 携带参数运行插件，例如 exec('py-echo', ['1', '2'])
export async function exec(plugin: string, ...params: string[]): Promise<output> {
  logger.debug(`exec plugin：${plugin}, params: ${params}`);
  process.env.PATH = addEnvPath(config.binPath);
  // 写入数据上报的渠道信息
  process.env[config.channelKey] = config.channelValue;
  const pluginInfo = await install(plugin);
  return startPlugin(pluginInfo, ...params);
}

export async function startPlugin(pluginInfo: PluginInfo, ...params: string[]): Promise<output> {
  return new Promise<output>((resolve, reject) => {
    const cp = spawn(config.runtimePlugin, [pluginInfo.path, ...params], {
      stdio: [ 'inherit', 'pipe', 'pipe' ],
      shell: true,
      windowsHide: true,
    });

    const outputs: output = {
      stdout: '',
      stderr: '',
      code: 0,
    };

    cp.stdout.on('data', (data: string) => {
      process.stdout.write(data);
      outputs.stdout += data;
    });

    cp.stderr.on('data', (data: string) => {
      process.stderr.write(data);
      outputs.stderr += data;
    });

    cp.on('close', (code: number) => {
      outputs.code = code;
      if (code === 0) {
        resolve(outputs);
      } else {
        reject(outputs);
      }
    });

    cp.on('error', (err: any) => {
      reject(err);
    });
  });
}

// 获取已安装的插件列表
export async function installedList(strict: boolean): Promise<Map<string, PluginInfo>> {
  const dirs = await fs.readdir(config.pluginRootDir);
  const list = new Map<string, PluginInfo>();
  for (let i = 0; i < dirs.length; i++) {
    const pi = await PluginInfo.fromDir(path.join(config.pluginRootDir, dirs[i]), strict);
    if (!pi) {
      continue;
    }
    list.set(pi.name, pi);
  }
  return list;
}
