import {promises as fsp} from 'fs';
import {join} from 'path';
import Zip from 'jszip';
import nunjucks from 'nunjucks';
import {generateLove, LoveVariant} from './love';

export async function entry(): Promise<void> {
  const themeDirectory: string = join(__dirname, '../sublime-text/');
  // Configure Nunjucks to use the templates for `source/vscode/themes/`.
  nunjucks.configure(themeDirectory, {
    lstripBlocks: true,
    trimBlocks: true,
    throwOnUndefined: true
  });

  const love: LoveVariant[] = generateLove();
  const sublimePackage: Zip = new Zip();
  for (const variant of love) {
    const template: string = await fsp.readFile(
      join(themeDirectory, 'love-template.sublime-color-scheme'),
      'utf8'
    );

    const outputPath: string = join(
      themeDirectory,
      `love-${variant.name}.sublime-color-scheme`
    );

    const output: string = nunjucks.renderString(template, {
      love: variant
    });
    let formattedOutput = '';
    for (const line of output.split('\n')) {
      // Don't include the line in the output if it's a comment:
      // * Starts with `//` or
      // * Starts with `/*` or
      // * Ends with `*/`
      // This allows us to use Nunjucks templating inside the JSON.
      if (
        /^\s+\/\/.+$/.exec(line) ||
        /^\s+\/\*.+$/.exec(line) ||
        /\*\/$/.exec(line)
      ) {
        continue;
      }

      formattedOutput += line;
      formattedOutput += '\n';
    }

    let outputObject: any;
    try {
      outputObject = JSON.parse(formattedOutput);
    } catch (error) {
      console.log('Could not parse formatted output as regular JSON:');
      throw error;
    }

    await fsp.writeFile(outputPath, JSON.stringify(outputObject));
    sublimePackage.file(
      `${String(outputObject.name)}.sublime-color-scheme`,
      JSON.stringify(outputObject)
    );
  }

  const zip: Buffer = await sublimePackage.generateAsync({type: 'nodebuffer'});
  await fsp.writeFile(join(themeDirectory, 'Love.sublime-package'), zip);
}

if (require.main === module) {
  entry();
}
