import { RendererApi } from '../common/rendererApi';
import * as fs from 'fs-extra';
import * as path from 'path';
import * as child_process from 'child_process';
import * as os from 'os';
import { AppDirectory } from './api';
import SerialPort from 'serialport';
import * as pio from './platformio';
import { Port } from '../common/mainApi';

// 一時ディレクトリに関する情報
const isDevelopment = process.env.NODE_ENV === 'development';
const isWindows = process.platform === 'win32';
const tmpDirName = isDevelopment ? 'tmp' : 'cq-interface-blockly';
const tmpRoot = isDevelopment ? tmpDirName : path.join(os.tmpdir(), tmpDirName);

export async function saveTextFile(rapi: RendererApi, filepath: string, contents: string): Promise<boolean> {
  try {
    const dirname = path.dirname(filepath);
    if (dirname != '' && dirname != '.' && !fs.existsSync(dirname)) {
      await fs.promises.mkdir(dirname, { recursive: true });
    }
    await fs.promises.writeFile(filepath, contents);
    return true;
  } catch (e) {
    const msg = `Error: ${e}`;
    rapi.err(msg);
    return false;
  }
}

export async function readTextFile(rapi: RendererApi, filepath: string): Promise<string | null> {
  try {
    return await fs.promises.readFile(filepath, 'utf8');
  } catch (e) {
    const msg = `Error: ${e}`;
    rapi.err(msg);
    return null;
  }
}

export async function makeTmpDirectory(): Promise<string> {
  if (!fs.existsSync(tmpRoot)) {
    await fs.promises.mkdir(tmpRoot, { recursive: true });
  }
  const dir = await fs.promises.mkdtemp(path.join(tmpRoot, 'tmp'));
  return dir;
}

export async function makeTmpProject(): Promise<string> {
  const dir = await makeTmpDirectory();
  await fs.copy(path.join(AppDirectory, 'prj-tmp'), dir);
  return dir;
}

/**
 * makeTmpDirectoryで作成したディレクトリを全て削除します。
 * プロセスの終了フックなどで使うことを想定しています。
 */
export function deleteAllTmpDirectoriesSync() {
  if (fs.existsSync(tmpRoot)) {
    if (isWindows) {
      child_process.execSync(`rmdir /s /q "${tmpRoot}"`);
    } else {
      child_process.execSync(`rm -rf '${tmpRoot}'`);
    }
  }
}

export async function build(rapi: RendererApi, directory: string): Promise<boolean> {
  try {
    await pio.build(rapi, directory);
    return true;
  } catch (e) {
    rapi.err(`fail to build: ${e}`);
    return false;
  }
}

export async function upload(rapi: RendererApi, directory: string, port: string): Promise<boolean> {
  try {
    await pio.upload(rapi, directory, port);
    return true;
  } catch (e) {
    rapi.err(`rail to uplaod: ${e}`);
    return false;
  }
}

export async function getPorts(): Promise<Port[]> {
  const p = await SerialPort.list();
  return p.map(i => {
    return {
      port: i.path,
      productId: i.productId ?? '',
      vendorId: i.vendorId ?? '',
    };
  });
}
