"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const puppeteer_1 = __importDefault(require("puppeteer"));
const argparse_1 = require("argparse");
const path_1 = require("path");
const promises_1 = require("fs/promises");
const URL = 'https://mattmcw.github.io/plotter-vision/';
const DOWNLOADS = './downloads';
const WIDTH_DEFAULT = 1920;
const HEIGHT_DEFAULT = 1080;
let PROCESSING = false;
let PROCESSING_MONITOR = false;
let WAITING = false;
async function delay(ms) {
    return new Promise((resolve, reject) => {
        return setTimeout(resolve, ms);
    });
}
function compare(before, after) {
    let downloaded = null;
    for (let file of after) {
        if (before.indexOf(file) === -1) {
            console.log(`Downloaded ${(0, path_1.join)(DOWNLOADS, file)}`);
            downloaded = (0, path_1.resolve)((0, path_1.join)(DOWNLOADS, file));
            break;
        }
    }
    return downloaded;
}
async function dir(path) {
    const files = await (0, promises_1.readdir)(path);
    return files.filter((el) => { return (0, path_1.extname)(el) === '.svg'; });
}
async function clearDownloads() {
    const files = await dir(DOWNLOADS);
    for (let file of files) {
        await (0, promises_1.unlink)((0, path_1.resolve)((0, path_1.join)(DOWNLOADS, file)));
    }
}
function cli() {
    const parser = new argparse_1.ArgumentParser({ description: 'STL to SVG', usage: '%(prog)s <options> [input] [output]' });
    parser.add_argument('input', { type: 'str', help: 'Input STL to render' });
    parser.add_argument('output', { type: 'str', help: 'Output SVG to write' });
    parser.add_argument('--width', '-W', { type: 'int', default: WIDTH_DEFAULT, help: `Width of window to render STL (default: ${WIDTH_DEFAULT})` });
    parser.add_argument('--height', '-H', { type: 'int', default: HEIGHT_DEFAULT, help: `Height of window to render STL (default: ${HEIGHT_DEFAULT})` });
    parser.add_argument('--load-delay', '-l', { type: 'int', default: 0, help: 'Number of milliseconds to wait after loading (default: 0)' });
    parser.add_argument('--save-delay', '-s', { type: 'int', default: 0, help: 'Number of milliseconds to wait before saving (default: 0)' });
    parser.add_argument('--theta', '-t', { type: 'float', default: null, help: 'Theta of the camera' });
    parser.add_argument('--psi', '-p', { type: 'float', default: null, help: 'Psi of the camera' });
    parser.add_argument('--radius', '-r', { type: 'float', default: null, help: 'Radius of the camera' });
    parser.add_argument('--center', '-c', { type: 'str', default: null, help: 'LookAt center' });
    parser.add_argument('--no-display', '-n', { action: 'store_true', default: true, help: 'No display' });
    return parser.parse_args();
}
async function download(page, dest, save) {
    let before;
    let after;
    let downloaded = null;
    before = await dir(DOWNLOADS);
    //console.dir(before)
    await page.click('#fileDownload');
    console.log(`Clicked download`);
    await delay(100);
    if (save > 0) {
        console.log(`Delaying for: ${save}ms`);
        await delay(save);
    }
    while (downloaded === null) {
        await delay(1);
        after = await dir(DOWNLOADS);
        downloaded = compare(before, after);
    }
    if (downloaded === null) {
        console.warn(`Cannot move download file to destination: ${dest}`);
        return;
    }
    await (0, promises_1.copyFile)(downloaded, dest);
    await (0, promises_1.unlink)(downloaded);
    console.dir(`${downloaded} => ${dest}`);
}
function startProcessing() {
    PROCESSING = true;
    PROCESSING_MONITOR = true;
}
async function waitForProcessing() {
    while (PROCESSING) {
        await delay(401);
    }
    return true;
}
async function main() {
    startProcessing();
    const args = cli();
    console.dir(args);
    const config = {
        headless: !args.no_display,
        args: [`--window-size=${args.width},${args.height}`]
    };
    await clearDownloads();
    const browser = await puppeteer_1.default.launch(config);
    const page = await browser.newPage();
    let lookat = [0, 0, 0];
    page.on('console', (message) => {
        const text = message.text();
        const type = message.type().substr(0, 3).toUpperCase();
        if (type === 'LOG' && text.trim() === 'hidden processing') {
            PROCESSING = true;
            PROCESSING_MONITOR = true;
        }
        else if (type === 'LOG' && text.indexOf('hidden processing ') !== -1 && text.indexOf(' segments ') !== -1) {
            PROCESSING_MONITOR = false;
            setTimeout(() => {
                if (!PROCESSING_MONITOR && PROCESSING) {
                    PROCESSING = false;
                    console.log('PROCESSING COMPLETE');
                }
            }, 100);
        }
        if (!text.startsWith('filtered ')) {
            console.log(`${type} ${text}`);
        }
    });
    const client = await page.target().createCDPSession();
    await client.send('Page.setDownloadBehavior', {
        behavior: 'allow',
        downloadPath: DOWNLOADS,
    });
    await page.setViewport({ width: args.width, height: args.height });
    await page.goto(URL, { waitUntil: 'networkidle2' });
    await delay(100);
    console.log(`Loading: ${args.input}`);
    startProcessing();
    const [fileChooser] = await Promise.all([
        page.waitForFileChooser(),
        page.click('#loadFileXml')
    ]);
    await fileChooser.accept([args.input]);
    startProcessing();
    await waitForProcessing();
    if (args.psi !== null || args.theta !== null) {
        console.log(`Adjusting the camera rotation`);
        startProcessing();
        await page.evaluate(`cameraView(${args.theta === null ? 0 : args.theta}, ${args.psi === null ? 0 : args.psi});`);
    }
    if (args.radius !== null) {
        console.log(`Adjusting the camera distance`);
        startProcessing();
        await page.evaluate(`camera_radius = ${args.radius}; reproject = true; vz = 0.00001;`); //vz = 0.00001;
    }
    if (args.center !== null) {
        lookat = args.center.split(',').map((el) => { return parseFloat(el); });
        await page.evaluate(`camera.lookat.x = ${lookat[0]};
                         camera.lookat.y = ${lookat[1]};
                         camera.lookat.z = ${lookat[2]};
                         vz = 0.00001;`);
    }
    if (args.load_delay > 0) {
        console.log(`Delaying for: ${args.load_delay}ms`);
        await delay(args.load_delay);
    }
    await waitForProcessing();
    await download(page, args.output, args.save_delay);
    await browser.close();
}
main();
//# sourceMappingURL=index.js.map