import * as fs from 'fs';
import * as path from 'path';
import * as glob from 'glob';
import { compile } from 'json-schema-to-typescript';

const root = path.resolve(path.join(__dirname, '..'));
const typeFilePath = path.join(root, 'generated.d.ts');
const schemaFilesPath = path.join(root, '**/*.schema.json');

const clearFile = async () => {
  fs.writeFileSync(typeFilePath, '', 'utf8');
};

const autoGeneratedMessage = `/*
  This file is generated automatically. **DO NOT MODIFY THIS FILE DIRECTLY**
  Updates are made by editing the JSON Schema files in the 'docs/' directory,
  then running the 'npm build' script.
*/
\n`

function createRootSchemaTemplate() {
  return {
    '$schema': 'http://json-schema.org/draft-07/schema#',
    'title': 'SchemaMergeRootStub',
    'anyOf': [] as {'$ref': string}[],
  };
}

async function run() {
  const files = await new Promise<string[]>((resolve, reject) => {
    glob(schemaFilesPath, { ignore: ['**/node_modules/**', './node_modules/**'] }, async (err, files) => {
      if (err) {
        reject(err);
      } else {
        resolve(files);
      }
    });
  });

  if (files.length === 0) {
    throw new Error(`Did not find any files in ${schemaFilesPath}`);
  }
  clearFile();

  // Create "root" schema with a $ref for every file, then pass to json-schema-to-typescript.
  // This avoids duplicate type definitions that happen when converting one schema at a time.
  const rootSchema = createRootSchemaTemplate();

  for (const file of files) {
    const relatePath = path.relative(root, file);
    rootSchema.anyOf.push({ '$ref': relatePath });
  }

  const outputTypescriptCode = await compile(rootSchema, rootSchema.title, {
    bannerComment: autoGeneratedMessage,
    strictIndexSignatures: true,
    declareExternallyReferenced: true,
    unreachableDefinitions: true,
  });

  fs.writeFileSync(typeFilePath, outputTypescriptCode, 'utf8');
}

run().then(() => {
  process.exit(0);
}).catch(error => {
  console.error('generate-types error');
  console.error(error);
  process.exit(1);
});
