/**
 * MotionVault → AtomX listener
 *
 * Roda DENTRO do iframe AtomX. Recebe postMessage do plugin MotionVault e
 * dispara o pprsequencer.exe a partir do contexto CEP do AtomX (Extension Id "Atom").
 *
 * Premiere identifica a "extension owner" do clipboard pelo Extension Id do
 * processo que chamou cep.process.createProcess. Quando o MotionVault chamava
 * direto, o Extension Id era "com.motionvault.panel" e Premiere ignorava o paste.
 * Agora a chamada acontece de dentro do AtomX → Extension Id "Atom" → autorizado.
 */
(function () {
    'use strict';

    function log() {
        try {
            var parts = ['[MV-Listener]'];
            for (var i = 0; i < arguments.length; i++) parts.push(arguments[i]);
            console.log.apply(console, parts);
        } catch (e) {}
    }

    function err() {
        try {
            var parts = ['[MV-Listener]'];
            for (var i = 0; i < arguments.length; i++) parts.push(arguments[i]);
            console.error.apply(console, parts);
        } catch (e) {}
    }

    // Persiste no debug log compartilhado com o MotionVault.
    function dbgFile(line) {
        try {
            var fs = require('fs'), pp = require('path'), os = require('os');
            var p = pp.join(os.tmpdir(), 'motionvault-debug.log');
            fs.appendFileSync(p, '[' + new Date().toISOString() + '] [MV-Listener] ' + line + '\n');
        } catch (e) {}
    }

    // Detecta path absoluto Windows sem regex (evita bug de [\\/] em literal JS).
    function isAbsoluteWinPath(s) {
        if (!s || s.length < 3) return false;
        var c0 = s.charCodeAt(0);
        var isLetter = (c0 >= 65 && c0 <= 90) || (c0 >= 97 && c0 <= 122);
        if (!isLetter) return false;
        if (s.charCodeAt(1) !== 58) return false;
        var c2 = s.charCodeAt(2);
        return c2 === 92 || c2 === 47;
    }

    // Normaliza file:///C:/x/y → C:\x\y
    function toNativePath(p) {
        if (!p) return '';
        return decodeURI(String(p)).replace(/^file:[\\\/]+/i, '').replace(/\//g, '\\');
    }

    // Resolve extPath do iframe AtomX. CSInterface dentro do iframe AtomX é
    // versão diferente — SystemPath.EXTENSION é undefined. Usamos 3 fallbacks:
    //   1) __adobe_cep__ nativo (sempre presente em CEP)
    //   2) cs.getSystemPath com string literal "extension"
    //   3) derivar de window.location.href (último recurso)
    function getExtPath() {
        // 1) __adobe_cep__ nativo
        try {
            if (window.__adobe_cep__ && typeof window.__adobe_cep__.getSystemPath === 'function') {
                var p1 = window.__adobe_cep__.getSystemPath('extension');
                if (p1) return toNativePath(p1);
            }
        } catch (e) {}

        // 2) CSInterface com string literal
        try {
            if (typeof CSInterface !== 'undefined') {
                var cs = new CSInterface();
                if (cs && typeof cs.getSystemPath === 'function') {
                    var EXTKEY = (CSInterface.SystemPath && CSInterface.SystemPath.EXTENSION) || 'extension';
                    var p2 = cs.getSystemPath(EXTKEY);
                    if (p2) return toNativePath(p2);
                }
            }
        } catch (e) {}

        // 3) derivar de window.location.href
        try {
            var loc = window.location.href || '';
            var clean = toNativePath(loc);
            // remove "\index.html" ou "\algo.html" do final
            var qi = clean.indexOf('?');
            if (qi > 0) clean = clean.substring(0, qi);
            var lastBs = clean.lastIndexOf('\\');
            if (lastBs > 0) clean = clean.substring(0, lastBs);
            return clean;
        } catch (e) {}

        return '';
    }

    function sanitizePrprojXml(xml, extPath) {
        var path = require('path');
        var fs = require('fs');
        var wavPlaceholder = path.join(extPath, '..', 'assets', 'empty.wav');
        var pngPlaceholder = path.join(extPath, '..', 'assets', 'empty.png');
        var tags = ['ActualMediaFilePath', 'FilePath', 'ConformedAudioPath', 'PeakFilePath'];
        var audioExt = /\.(wav|mp3|aif|aiff|m4a|aac|flac|ogg)$/i;
        var patched = 0;

        for (var i = 0; i < tags.length; i++) {
            var tag = tags[i];
            var re = new RegExp('<' + tag + '>([^<]*)</' + tag + '>', 'g');
            xml = xml.replace(re, function (full, inner) {
                if (!isAbsoluteWinPath(inner)) return full;
                try { if (fs.existsSync(inner)) return full; } catch (e) {}
                patched++;
                var placeholder = audioExt.test(inner) ? wavPlaceholder : pngPlaceholder;
                return '<' + tag + '>' + placeholder + '</' + tag + '>';
            });
        }
        return { xml: xml, patched: patched };
    }

    function decodeAtomxAsset(absPath) {
        var fs = require('fs');
        var zlib = require('zlib');
        var raw = fs.readFileSync(absPath, 'utf8').trim();
        var b64 = raw.replace(/[^A-Za-z0-9+/=]/g, '');
        var buf = zlib.gunzipSync(Buffer.from(b64, 'base64'));
        return buf.toString('utf8');
    }

    function writeTmpPrproj(xmlString, basename) {
        var fs = require('fs'), pp = require('path'), os = require('os');
        var dir = pp.join(os.tmpdir(), 'motionvault-atomx');
        try { fs.mkdirSync(dir, { recursive: true }); } catch (e) {}
        var safe = String(basename || 'asset').replace(/[^A-Za-z0-9._-]+/g, '_');
        var tmp = pp.join(dir, safe + '_' + Date.now() + '.prproj');
        fs.writeFileSync(tmp, xmlString);
        return tmp;
    }

    function runPprSequencer(prprojPath, packprint) {
        var atomxExtPath = getExtPath();
        var path = require('path');
        var fs = require('fs');
        var binPath = path.join(atomxExtPath, 'bin', 'pprsequencer.exe');

        if (!fs.existsSync(binPath)) throw new Error('pprsequencer.exe não encontrado em ' + binPath);
        if (!fs.existsSync(prprojPath)) throw new Error('.prproj tmp não encontrado: ' + prprojPath);

        // Foco no Premiere via PowerShell AppActivate (mesma técnica do AtomX).
        try {
            window.cep.process.createProcess(
                'cmd.exe', '/c',
                'powershell -NoProfile -WindowStyle Hidden -Command "(New-Object -ComObject WScript.Shell).AppActivate(\'Adobe Premiere\')" > nul 2>&1'
            );
        } catch (e) { dbgFile('AppActivate erro: ' + (e.message || e)); }

        // Pequeno delay pra o foco assentar antes do spawn do exe.
        var hash = String(packprint || 'mv-' + Date.now());
        var spawnAt = Date.now() + 250;
        while (Date.now() < spawnAt) {}

        var res = window.cep.process.createProcess(binPath, prprojPath, hash);
        dbgFile('createProcess result: ' + JSON.stringify(res));

        if (!res || res.err !== 0) {
            throw new Error('createProcess err=' + (res && res.err));
        }
        return { pid: res.data, hash: hash, binPath: binPath };
    }

    function handleApply(msg) {
        var assetPath = msg && msg.file;
        if (!assetPath) {
            err('apply sem file no message');
            return;
        }
        dbgFile('===== APPLY (via iframe AtomX) =====');
        dbgFile('file=' + assetPath + ' subType=' + msg.subType + ' name=' + msg.name);

        try {
            var atomxExtPath = getExtPath();
            var xml = decodeAtomxAsset(assetPath);
            dbgFile('decoded ' + xml.length + ' chars');

            var san = sanitizePrprojXml(xml, atomxExtPath);
            dbgFile('sanitized: ' + san.patched + ' refs externas');

            var pp = require('path');
            var basename = pp.basename(assetPath).replace(/\.atomxasset$/i, '');
            var tmp = writeTmpPrproj(san.xml, basename);
            dbgFile('tmp=' + tmp);

            var r = runPprSequencer(tmp, msg.packprint);
            dbgFile('pprsequencer pid=' + r.pid + ' hash=' + r.hash);
            log('apply ok pid=' + r.pid);
        } catch (e) {
            dbgFile('✗ apply throw: ' + (e.message || e));
            err('apply throw:', e);
        }
    }

    // Escuta postMessage do MotionVault.
    window.addEventListener('message', function (e) {
        var d = e && e.data;
        if (!d || d.source !== 'motionvault') return;
        if (d.type === 'MV_APPLY') {
            handleApply(d);
        }
    });

    // Avisa o MotionVault que o listener está pronto.
    function announceReady() {
        try {
            window.parent.postMessage({ type: 'ATOMX_READY' }, '*');
            log('ready');
            dbgFile('listener ready (ATOMX_READY posted to parent)');
        } catch (e) { err('announceReady throw:', e); }
    }

    if (document.readyState === 'complete' || document.readyState === 'interactive') {
        setTimeout(announceReady, 200);
    } else {
        window.addEventListener('DOMContentLoaded', function () { setTimeout(announceReady, 200); });
    }

    log('boot');
})();
