import fs from "fs"
import { extname } from "path"
import { format } from "prettier"

export function file(extension: string, content = "") {
  const path = `./.${(Date.now() - 1677e9).toString(36)}${extension}`
  fs.writeFileSync(path, content)

  process.on("SIGINT", () => fs.unlinkSync(path))

  return {
    path,
    rm: () => fs.unlinkSync(path),
  }
}

file.js = (content?: string) => file(".js", content)

export function map<T, R>(list: T[], fn: (item: T, index: number) => Promise<R>) {
  return Promise.all(list.map(fn))
}

/**
 * Write a file with Prettier formatting.
 */
export async function writeFormatted(path: string, content: string) {
  const ext = extname(path)
  const formatted = await format(content, {
    parser: ext === ".ts" ? "babel-ts" : ext === ".js" ? "babel" : undefined,
  })
  return fs.promises.writeFile(path, formatted)
}

// https://github.com/nathanbabcock/picocolors-browser/tree/d98747d1e7dd58390044ff0696b6d10995a94de3
// ISC License. Copyright (c) 2021 Alexey Raspopov, Kostiantyn Denysov, Anton Verinov
export namespace c {
  const enabled = !("NO_COLOR" in process.env)

  const formatter = (open: string, close: string, replace = open) =>
    enabled
      ? (input: number | string) => {
          const string = "" + input
          const index = string.indexOf(close, open.length)
          return index !== -1
            ? open + replaceClose(string, close, replace, index) + close
            : open + string + close
        }
      : String

  function replaceClose(
    string: string,
    close: string,
    replace: string,
    index: number,
  ): string {
    const start = string.substring(0, index) + replace
    const end = string.substring(index + close.length)
    const nextIndex = end.indexOf(close)
    return nextIndex !== -1
      ? start + replaceClose(end, close, replace, nextIndex)
      : start + end
  }

  export const reset = enabled ? (s: string) => `\x1b[0m${s}\x1b[0m` : String
  export const bold = formatter("\x1b[1m", "\x1b[22m", "\x1b[22m\x1b[1m")
  export const dim = formatter("\x1b[2m", "\x1b[22m", "\x1b[22m\x1b[2m")
  export const italic = formatter("\x1b[3m", "\x1b[23m")
  export const underline = formatter("\x1b[4m", "\x1b[24m")
  export const inverse = formatter("\x1b[7m", "\x1b[27m")
  export const hidden = formatter("\x1b[8m", "\x1b[28m")
  export const strikethrough = formatter("\x1b[9m", "\x1b[29m")
  export const black = formatter("\x1b[30m", "\x1b[39m")
  export const red = formatter("\x1b[31m", "\x1b[39m")
  export const green = formatter("\x1b[32m", "\x1b[39m")
  export const yellow = formatter("\x1b[33m", "\x1b[39m")
  export const blue = formatter("\x1b[34m", "\x1b[39m")
  export const magenta = formatter("\x1b[35m", "\x1b[39m")
  export const cyan = formatter("\x1b[36m", "\x1b[39m")
  export const white = formatter("\x1b[37m", "\x1b[39m")
  export const gray = formatter("\x1b[90m", "\x1b[39m")
  export const bgBlack = formatter("\x1b[40m", "\x1b[49m")
  export const bgRed = formatter("\x1b[41m", "\x1b[49m")
  export const bgGreen = formatter("\x1b[42m", "\x1b[49m")
  export const bgYellow = formatter("\x1b[43m", "\x1b[49m")
  export const bgBlue = formatter("\x1b[44m", "\x1b[49m")
  export const bgMagenta = formatter("\x1b[45m", "\x1b[49m")
  export const bgCyan = formatter("\x1b[46m", "\x1b[49m")
  export const bgWhite = formatter("\x1b[47m", "\x1b[49m")
}
