import cli from 'cli';
import { convertSong } from './convert.js';
import { promises } from 'fs';
import { prettyPrint} from './lib/prettyPrint.js';
import { resolve, dirname} from 'path';
import { fileURLToPath } from 'url';

const { readFile, writeFile } = promises;

let options = cli({
  name: 'ZzFXM Song Conversion Tool',
  packageJson: resolve(dirname(fileURLToPath(import.meta.url)), 'package.json'),
  inputPaths: 'single',
  outputPath: 'optional',
  options: [
    { name: 'ignore-errors', alias: 'i', type: Boolean, description: 'Ignore incompatability errors with ZzxFM and the source song.' },
    { name: 'no-instruments', alias: 'n', type: Boolean, description: 'Don\'t generate instrument data.'},
    { name: 'sane-instruments', alias: 's', type: Boolean, description: 'Only generate data for known instruments.'},
    { name: 'pretty-print', alias: 'p', type: Boolean, description: 'Generate human-readable output file.'},
    { name: 'format', alias: 'f', values: ['none', 'esm'], type: String, description: `Output format.`, defaultValue: 'none'},
  ]
});

const run = async (options) => {
  const buffer = await readFile(options.paths[0]);
  const { song, warnings } = convertSong(buffer, options);
  const assignedInstruments = []
  const unassignedInstruments = []
  const instrumentNames = [];

  let instrumentCount = song.getInstrumentCount();

  for (let i = 0; i <= instrumentCount - 1; i++) {
    instrumentNames.push(song.getInstrumentName(i));
    if (!song.getInstrument(i).length || song.getInstrument(i)[0] === 0) {
      unassignedInstruments.push(song.getInstrumentName(i))
    } else {
      assignedInstruments.push(song.getInstrumentName(i))
    }
  }

  console.log(`- Converted "${song.title}"`);
  console.log(`  • Sequence length: ${song.getSequenceLength()}`);
  console.log(`  • Instruments: ${song.getInstrumentCount()}`);
  console.log(`  • Patterns: ${song.getPatternCount()}`);
  console.log(`  • Speed: ${song.speed} BPM`);

  if (assignedInstruments.length) {
    console.log(`- Created ${assignedInstruments.length} ZzFX instruments`);
  }

  if (unassignedInstruments.length) {
    console.log(`- Created ${unassignedInstruments.length} empty instruments`);
  }

  if (warnings.length) {
    console.log();
    console.log(`WARNING: Conversion completed without error but you should be aware of the following, which could impact fidelity:`);
    warnings.map(warning => console.log(`  • ${warning}`))
  }

  let dest;
  if (options.paths[1]) {
    dest = options.paths[1];
  } else if (song.title) {
    dest = `${song.title}.js`;
  } else {
    dest = 'song.js';
  }

  let code = song.toString();
  if (options.prettyPrint) {
    code = prettyPrint(code, instrumentNames);
  }

  if (options.format === 'esm') {
    code = `export default ${code};`;
  }

  await writeFile(dest, code);
  console.log(`\nFile "${dest}" written successfully.`);
}


run(options).catch(e => {
  let {message, code} = e;
  if (code == 'ENOENT') {
    message = `File '${e.path}' not found.`;
  }
  if (code == 'ERR_ZZFXM_NO_SUPPORT') {
    message = `${e.message}. Try again with the -i argument to ignore errors.`;
  }
  console.log(message);
});