// This script is intended to be used from the package root (lib directory), from npm scripts.
//
// Usage:
//
//   npm run build
//   => bump version number to next pre-release suffix and update index.js
//
//   npm run build -- 1.10.21818
//   => set official version number and update index.js
//

import * as fs from 'fs';
import * as ts from 'typescript';
import * as process from 'process';
import * as cs from 'child_process';
import * as esbuild from 'esbuild';

function findFilesRecursively(path: string, pattern: RegExp): string[]
{
    let result: string[] = [];
    fs.readdirSync(path).forEach((name: string) => {
        if(name[0] != '.') {
            let subpath: string = path + '/' + name;
            if(fs.statSync(subpath).isDirectory()) {
                result.push(...findFilesRecursively(subpath, pattern));
            } else if(pattern.test(name)){
                result.push(subpath);
            }
        }
    })
    return result;
}

function transpile(fcttypes: string[])
{
    let options: ts.CompilerOptions = {
        target: ts.ScriptTarget.ES2017,
        strict: true,
        moduleResolution: ts.ModuleResolutionKind.NodeJs,
        allowSyntheticDefaultImports: true,
        esModuleInterop: true,
        skipLibCheck: true,
        outDir: 'obj'
    };
    // Compile all .ts files within src
    console.log('Transpiling '+fcttypes.toString()+' TypeScript files');
    let commonFiles: string[] = findFilesRecursively('src/common_code', /\.ts$/);

    let mainFiles: string[] = findFilesRecursively('src', /yoctopuce_SD_plugin\.ts$/);
    let files= [  ...commonFiles, ...mainFiles]
    for (let i:number=0;i<fcttypes.length;i++ )
    {
        let inputFiles: string[] = findFilesRecursively('src/' + fcttypes[i], /\.ts$/);
        files=[...files, ...inputFiles]
    }

    let program = ts.createProgram(files, options); // aka array merge

    let emitResult = program.emit();
    let allDiagnostics = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics);
    console.log(allDiagnostics.length+' messages generated by TypeScript compiler');
    allDiagnostics.forEach(diagnostic => {
        if (diagnostic.file) {
            let { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start!);
            let message = ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n");
            console.log(`${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`);
        } else {
            console.log(ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n"));
        }
    });
}

async function bundle(fcttypes : string[])
{
    await esbuild.build({
        entryPoints: ['obj/yoctopuce_SD_plugin.js'],
        bundle: true,
        format: 'iife',
        globalName: 'YElgatoSD',
        sourcemap: false,
        outfile: 'dist/com.yoctopuce.modules.sdPlugin/Yoctopuce_plugin.js',
    });

    for (let i:number  =0; i<fcttypes.length;i++)
    {  let fcttype :string= fcttypes[i];
        await esbuild.build({
            entryPoints: ['obj/' + fcttype + '/'+fcttype+'_pi.js'],
            bundle: true,
            format: 'iife',
            globalName: 'YElgatoSD',
            sourcemap: false,
            outfile: 'dist/com.yoctopuce.modules.sdPlugin/' + fcttype + '_pi.js',

        });
    }
}

function copySrcFiles(srcpath:string )
{
    let files = findFilesRecursively(srcpath, /.*\.(html|json|css|svg|js|png)/);
    for(let fpath of files) {
        let fname = fpath.slice(fpath.lastIndexOf('/')+1);
        fs.copyFileSync(fpath, 'dist/com.yoctopuce.modules.sdPlugin/'+fname);
    }
}

function copyAllSrcFiles(fcttypes:string[])
{ if (!fs.existsSync("dist")) fs.mkdirSync("dist");
  if (!fs.existsSync("dist/com.yoctopuce.modules.sdPlugin")) fs.mkdirSync("dist/com.yoctopuce.modules.sdPlugin");
  if (!fs.existsSync("dist/Release")) fs.mkdirSync("dist/Release");
  copySrcFiles("src/common_artwork")
  copySrcFiles("src/common_code")
  for (let i:number=0;i<fcttypes.length;i++)
  {
      copySrcFiles("src/" + fcttypes[i])
      copySrcFiles("src/" + fcttypes[i] + "/artwork")
  }
  fs.copyFileSync("src/index.html", 'dist/com.yoctopuce.modules.sdPlugin/index.html');
  fs.copyFileSync("src/manifest.json", 'dist/com.yoctopuce.modules.sdPlugin/manifest.json');
  if (!fs.existsSync("dist/com.yoctopuce.modules.sdPlugin/previews")) fs.mkdirSync('dist/com.yoctopuce.modules.sdPlugin/previews')
  fs.copyFileSync("src/previews/1-preview.png", 'dist/com.yoctopuce.modules.sdPlugin/previews/1-preview.png');
  fs.copyFileSync("src/previews/2-preview.png", 'dist/com.yoctopuce.modules.sdPlugin/previews/2-preview.png');

}

function makePlugin()
 {  if (fs.existsSync("bin/DistributionTool.exe"))
     {   if (fs.existsSync("dist/release/com.yoctopuce.modules.streamDeckPlugin"))
           {
               fs.rmSync("dist/release/com.yoctopuce.modules.streamDeckPlugin");
           }
        let res: any =null;
         try {
             res = cs.execFileSync("bin/DistributionTool.exe", ["-b", "-i", 'dist\\com.yoctopuce.modules.sdPlugin', "-o", "dist\\Release"]) as unknown
         } catch(e)
         {   console.log((e as any).output.toString());
             throw new Error('Failed to create bundle  com.yoctopuce.modules.streamDeckPlugin')
         }
         //let message :string =  new TextDecoder().decode(res.stdout)
         console.log(new TextDecoder().decode(res))
     }
     else console.log("bin/DistributionTool.exe not available, com.yoctopuce.modules.streamDeckPlugin won't be created ")

 }

async function cleanup(full: boolean)
{
    // Cleanup intermediate object files
    let objFiles: string[] = findFilesRecursively('obj', /\.(ts|js|map)$/);
    for(let file of objFiles) {
        fs.unlinkSync(file);
    }

    if(full) {
        // Cleanup all files
        let distFiles: string[] = findFilesRecursively('dist', /\.(js|map|html|png|svg|css)$/);
        for(let file of distFiles) {
            fs.unlinkSync(file);
        }
    }

    fs.unlinkSync('bin/build.js.map');
    fs.unlinkSync('bin/build.js');
}

let args: string[] = process.argv.slice(2);
if(args.length == 0) {
    console.log("command expected")
} else {

    switch(args[0])
    {
        case "build":
            if(args.length <= 1)
                console.log("build type expect expected, for install relay")
            {  //let fcttype: string = args[1].toLowerCase();
               let fcttypes:string[]  = ["relay","currentLoopOutput","voltageOutput","servo","wakeUpMonitor","buzzer","colorLedCluster"];
                transpile(fcttypes);
                bundle(fcttypes);
                copyAllSrcFiles(fcttypes);
                makePlugin();
             }
            break;
        case "cleanup-release":
            cleanup(false);
            break;
        case "cleanup-full":
            cleanup(true);
            break;
    }
}

