#target indesign
/*
 MRC - Coda esportazione PDF - v1.1
 Configurazione:
 cartella_relativa|replace oppure cartella_relativa|rename
 preset|pagine|livelli|nome

 Esempio:
 pdf|replace
 [Qualita tipografica]|1-3,5|*|[indd] [preset]

 Livelli: * = mantiene la visibilita originale; Nome A,Nome B = rende visibili
 solo i livelli elencati. I livelli non stampabili restano non stampabili.
 Le stringhe [indd] e [preset] sono sostituite al momento dell'esportazione.
*/
(function () {
    if (app.documents.length === 0) { alert('Apri un documento InDesign prima di avviare lo script.'); return; }
    var doc = app.activeDocument;
    if (!doc.saved) { alert('Salva il documento InDesign prima di creare la coda PDF.'); return; }
    var presets = app.pdfExportPresets.everyItem().getElements();
    if (!presets.length) { alert('Nessun preset PDF disponibile.'); return; }

    function trim(s) { return String(s).replace(/^\s+|\s+$/g, ''); }
    function linesOf(s) { return String(s).replace(/\r\n?/g, '\n').split('\n'); }
    function baseName(s) { return String(s).replace(/\.indd$/i, ''); }
    function safeName(s) { return trim(s).replace(/[\\\/:*?"<>|]/g, '_').replace(/[. ]+$/g, ''); }
    function contains(arr, value) { for (var i=0;i<arr.length;i++) if (arr[i] === value) return true; return false; }
    function findPreset(name) {
        for (var i=0;i<presets.length;i++) if (presets[i].name === name) return presets[i];
        return null;
    }
    function makeName(template, preset) {
        return safeName(String(template).replace(/\[indd\]/gi, baseName(doc.name)).replace(/\[preset\]/gi, preset));
    }
    function resolveFolder(folder) {
        folder = trim(folder).replace(/\\/g, '/');
        if (/^\//.test(folder) || /^[A-Za-z]:/.test(folder) || /(^|\/)\.\.(\/|$)/.test(folder))
            throw Error('La cartella deve essere relativa alla posizione del file INDD, senza ..');
        var root = doc.filePath;
        if (!folder || folder === '.') return root;
        return Folder(root.fsName + '/' + folder);
    }
    function configParse(raw) {
        var ls = linesOf(raw), nonempty = [], i;
        for (i=0;i<ls.length;i++) { var t=trim(ls[i]); if (t && t.charAt(0) !== '#') nonempty.push({line:i+1, value:t}); }
        if (nonempty.length < 2) throw Error('Servono la riga generale e almeno una riga PDF.');
        var general=nonempty[0].value.split('|');
        if (general.length !== 2) throw Error('Riga generale: cartella|replace oppure cartella|rename.');
        var folder=trim(general[0]), behavior=trim(general[1]).toLowerCase();
        if (behavior === 'sovrascrivi') behavior='replace';
        if (behavior === 'rinomina') behavior='rename';
        if (behavior !== 'replace' && behavior !== 'rename') throw Error('Comportamento non valido: '+behavior);
        var target = resolveFolder(folder);
        var rows=[];
        for (i=1;i<nonempty.length;i++) {
            var s=nonempty[i].value, parts=s.split('|');
            if (parts.length !== 4) throw Error('Riga '+nonempty[i].line+': occorrono 4 campi separati da |.');
            for (var c=0;c<parts.length;c++) parts[c]=trim(parts[c]);
            var preset = findPreset(parts[0]);
            if (!preset) throw Error('Riga '+nonempty[i].line+': preset non trovato: '+parts[0]);
            var pages=parts[1] || '*';
            if (pages !== '*' && !/^[+\w\s,\-:]+$/.test(pages)) throw Error('Riga '+nonempty[i].line+': intervallo pagine non valido.');
            var layerNames=[];
            if (parts[2] && parts[2] !== '*') {
                var names=parts[2].split(',');
                for (var j=0;j<names.length;j++) {
                    var n=trim(names[j]);
                    if (!n) continue;
                    var found=false;
                    for (var k=0;k<doc.layers.length;k++) if (doc.layers[k].name === n) {found=true;break;}
                    if (!found) throw Error('Riga '+nonempty[i].line+': livello non trovato: '+n);
                    if (!contains(layerNames,n)) layerNames.push(n);
                }
                if (!layerNames.length) throw Error('Riga '+nonempty[i].line+': nessun livello selezionato.');
            }
            var outputName=makeName(parts[3] || '[indd] [preset]',parts[0]);
            if (!outputName) throw Error('Riga '+nonempty[i].line+': nome PDF vuoto.');
            rows.push({preset:preset,pages:pages,layers:parts[2] || '*',layerNames:layerNames,name:outputName,line:nonempty[i].line});
        }
        return {folder:target,behavior:behavior,rows:rows};
    }
    function destination(folder, name, behavior, reserved) {
        var desired=File(folder.fsName + '/' + name + '.pdf');
        if (behavior === 'replace') return desired;
        var candidate=desired, n=2;
        while (candidate.exists || contains(reserved,candidate.fsName)) {
            candidate=File(folder.fsName + '/' + name + '_' + n + '.pdf'); n++;
        }
        return candidate;
    }
    function runQueue(raw) {
        var cfg=configParse(raw);
        // Risoluzione preventiva di tutti i nomi e verifica delle collisioni.
        var reserved=[], outputs=[], i;
        for (i=0;i<cfg.rows.length;i++) {
            var out=destination(cfg.folder,cfg.rows[i].name,cfg.behavior,reserved);
            // In replace due righe con lo stesso nome sovrascrivono la prima: e' potenzialmente distruttivo.
            if (cfg.behavior === 'replace' && contains(reserved,out.fsName))
                throw Error('Due righe generano lo stesso PDF: '+out.name+'; modifica il nome.');
            outputs.push(out); reserved.push(out.fsName);
        }
        if (!cfg.folder.exists && !cfg.folder.create()) throw Error('Impossibile creare la cartella: '+cfg.folder.fsName);
        var originalVisibility=[], originalRange=app.pdfExportPreferences.pageRange;
        var originalLayerMode=app.pdfExportPreferences.exportWhichLayers;
        var completed=[], problem=null;
        for (i=0;i<doc.layers.length;i++) originalVisibility.push(doc.layers[i].visible);
        try {
            for (i=0;i<cfg.rows.length;i++) {
                var row=cfg.rows[i];
                try {
                    for (var l=0;l<doc.layers.length;l++) {
                        doc.layers[l].visible = (row.layers === '*') ? originalVisibility[l] : contains(row.layerNames,doc.layers[l].name);
                    }
                    app.pdfExportPreferences.pageRange = (row.pages === '*') ? PageRange.ALL_PAGES : row.pages;
                    app.pdfExportPreferences.exportWhichLayers = ExportLayerOptions.EXPORT_VISIBLE_PRINTABLE_LAYERS;
                    doc.exportFile(ExportFormat.PDF_TYPE,outputs[i],false,row.preset);
                    completed.push(outputs[i].name);
                } catch (err) { problem='Riga '+row.line+' ('+outputs[i].name+'): '+err; break; }
            }
        } finally {
            for (var r=0;r<doc.layers.length;r++) { try { doc.layers[r].visible=originalVisibility[r]; } catch (ignored) {} }
            try {app.pdfExportPreferences.pageRange=originalRange;} catch (ignored2) {}
            try {app.pdfExportPreferences.exportWhichLayers=originalLayerMode;} catch (ignored3) {}
        }
        var report='PDF esportati: '+completed.length+' / '+cfg.rows.length+'\nCartella: '+cfg.folder.fsName;
        if (completed.length) report+='\n\n'+completed.join('\n');
        if (problem) report+='\n\nERRORE: '+problem;
        alert(report);
    }

    // ScriptUI non offre uno scrolling automatico affidabile dei dialog:
    // il corpo e' un viewport con scrollbar; la barra dei comandi resta fissa.
    var screenH=800, screenW=1200;
    try {
        var b=$.screens[0];
        screenH=b.bottom-b.top; screenW=b.right-b.left;
    } catch (ignoredScreen) {}
    var maxH=Math.max(480,screenH-100);
    var windowW=Math.min(820,Math.max(600,screenW-100));
    var w=new Window('dialog','MRC | Coda di esportazione PDF');
    w.orientation='column'; w.alignChildren=['fill','top']; w.spacing=8; w.margins=12;
    w.minimumSize.width=windowW;

    var scrollRow=w.add('group');
    scrollRow.orientation='row'; scrollRow.alignChildren=['fill','fill'];
    scrollRow.spacing=4; scrollRow.margins=0;
    var viewport=scrollRow.add('panel');
    viewport.margins=0;
    viewport.alignment=['fill','fill'];
    var content=viewport.add('group');
    content.orientation='column'; content.alignChildren=['fill','top'];
    content.spacing=9; content.margins=8;
    var vScroll=scrollRow.add('scrollbar');
    vScroll.preferredSize.width=16;
    vScroll.alignment=['right','fill'];

    var gen=content.add('panel',undefined,'Generali'); gen.orientation='column'; gen.alignChildren=['fill','top']; gen.margins=12;
    var pathLine=gen.add('group'); pathLine.add('statictext',undefined,'Sottocartella relativa all\'INDD:');
    var pathInput=pathLine.add('edittext',undefined,''); pathInput.characters=32;
    gen.add('statictext',undefined,'Vuoto = stessa cartella del documento; es. pdf oppure output/stampa');
    var modeLine=gen.add('group'); modeLine.add('statictext',undefined,'File esistente:');
    var replace=modeLine.add('radiobutton',undefined,'Sovrascrivi (replace)');
    var rename=modeLine.add('radiobutton',undefined,'Rinomina (rename)'); replace.value=true;

    var pg=content.add('panel',undefined,'Componi un PDF'); pg.orientation='column'; pg.alignChildren=['fill','top']; pg.margins=12;
    var presetRow=pg.add('group'); presetRow.add('statictext',undefined,'Preset PDF:');
    var presetNames=[]; for (var pp=0;pp<presets.length;pp++) presetNames.push(presets[pp].name);
    var presetDrop=presetRow.add('dropdownlist',undefined,presetNames); presetDrop.minimumSize.width=390; presetDrop.selection=0;
    var pageRow=pg.add('group'); pageRow.add('statictext',undefined,'Pagine:');
    var pageInput=pageRow.add('edittext',undefined,'*'); pageInput.characters=28;
    pageRow.add('statictext',undefined,'* = tutte; es. 1-3,5,8-10');
    var layerPanel=pg.add('panel',undefined,'Livelli visibili nel PDF (seleziona i livelli da includere)');
    layerPanel.orientation='column'; layerPanel.alignChildren=['fill','top']; layerPanel.margins=10;
    var allLayers=layerPanel.add('checkbox',undefined,'Mantieni visibilita attuale (*)'); allLayers.value=true;
    var layerGrid=layerPanel.add('group'); layerGrid.orientation='row';
    layerGrid.alignChildren=['fill','top']; layerGrid.spacing=12;
    var layerChecks=[];
    // Distribuzione per colonne: anche con molti livelli l'altezza resta contenuta.
    var columns=Math.min(4,Math.max(2,Math.ceil(doc.layers.length/5)));
    var rowsPerColumn=Math.ceil(doc.layers.length/columns);
    var layerColumns=[];
    for (var col=0;col<columns;col++) {
        var layerColumn=layerGrid.add('group');
        layerColumn.orientation='column'; layerColumn.alignChildren=['left','top'];
        layerColumn.spacing=3; layerColumn.preferredSize.width=Math.floor((windowW-105)/columns);
        layerColumns.push(layerColumn);
    }
    for (var ll=0;ll<doc.layers.length;ll++) {
        var columnIndex=Math.floor(ll/rowsPerColumn);
        var ck=layerColumns[columnIndex].add('checkbox',undefined,doc.layers[ll].name);
        ck.value=doc.layers[ll].visible; ck.enabled=false;
        ck.helpTip=doc.layers[ll].name;
        layerChecks.push(ck);
    }
    allLayers.onClick=function(){for(var j=0;j<layerChecks.length;j++)layerChecks[j].enabled=!allLayers.value;};
    var nameRow=pg.add('group'); nameRow.add('statictext',undefined,'Nome:');
    var nameInput=nameRow.add('edittext',undefined,'[indd] [preset]'); nameInput.characters=46;
    pg.add('statictext',undefined,'Usa [indd] e [preset] come variabili; puoi scrivere prefissi e suffissi.');
    var addRow=pg.add('group'); addRow.alignment='right';
    var addButton=addRow.add('button',undefined,'Aggiungi PDF alla coda');

    var rawPanel=content.add('panel',undefined,'Configurazione completa (modificabile e incollabile)');
    rawPanel.orientation='column'; rawPanel.alignChildren=['fill','top']; rawPanel.margins=12;
    var rawInput=rawPanel.add('edittext',undefined,'|replace',{multiline:true,scrolling:true,wantReturn:true});
    rawInput.preferredSize=[windowW-90,145];
    rawPanel.add('statictext',undefined,'Prima riga: cartella|replace/rename. Seguono: preset|pagine|livelli|nome');

    // I pulsanti sono fuori dal viewport: sono sempre raggiungibili.
    var buttons=w.add('group'); buttons.alignment='right';
    var readButton=buttons.add('button',undefined,'Leggi generali dal blocco');
    var cancelButton=buttons.add('button',undefined,'Annulla',{name:'cancel'});
    var exportButton=buttons.add('button',undefined,'Esporta coda',{name:'ok'});

    var scrollOffset=0, maxScroll=0;
    function updateScroll() {
        var height=content.size.height;
        var visible=viewport.size.height;
        maxScroll=Math.max(0,height-visible+10);
        vScroll.maxvalue=Math.max(1,maxScroll);
        vScroll.value=Math.min(scrollOffset,maxScroll);
        vScroll.enabled=maxScroll>0;
        vScroll.visible=maxScroll>0;
        moveScroll();
    }
    function moveScroll() {
        scrollOffset=Math.max(0,Math.min(maxScroll,vScroll.value));
        // Non forzare il relayout qui: annullerebbe il posizionamento.
        content.location=[8,8-Math.round(scrollOffset)];
    }
    vScroll.onChanging=moveScroll;
    vScroll.onChange=moveScroll;
    // Il contenuto viene misurato interamente, poi limitato in altezza.
    w.layout.layout(true);
    var fullContentH=content.size.height;
    var footH=buttons.size.height;
    var viewH=Math.min(fullContentH+16,Math.max(320,maxH-footH-65));
    viewport.preferredSize=[windowW-50,viewH];
    viewport.maximumSize.height=viewH;
    scrollRow.preferredSize.height=viewH;
    scrollRow.maximumSize.height=viewH;
    w.maximumSize.height=maxH;
    w.layout.layout(true);
    updateScroll();
    w.onShow=function(){updateScroll();};
    function writeGeneral() {
        var ls=linesOf(rawInput.text);
        if (!ls.length) ls=[''];
        ls[0]=trim(pathInput.text)+'|'+(replace.value?'replace':'rename');
        rawInput.text=ls.join('\n');
    }
    pathInput.onChange=writeGeneral;
    replace.onClick=writeGeneral; rename.onClick=writeGeneral;
    addButton.onClick=function() {
        var p=presetDrop.selection ? presetDrop.selection.text : '';
        if (!p) {alert('Seleziona un preset.');return;}
        var names='*';
        if (!allLayers.value) {
            var selected=[];
            for(var i=0;i<layerChecks.length;i++) if(layerChecks[i].value) selected.push(layerChecks[i].text);
            if(!selected.length) {alert('Seleziona almeno un livello, oppure mantieni la visibilita attuale.');return;}
            names=selected.join(',');
        }
        if (p.indexOf('|')>=0 || names.indexOf('|')>=0 || nameInput.text.indexOf('|')>=0) {
            alert('Il carattere | e riservato come separatore.');return;
        }
        var line=p+'|'+(trim(pageInput.text)||'*')+'|'+names+'|'+(trim(nameInput.text)||'[indd] [preset]');
        var raw=String(rawInput.text).replace(/\s+$/,'');
        rawInput.text=raw+'\n'+line;
    };
    readButton.onClick=function() {
        var first=linesOf(rawInput.text)[0].split('|');
        if(first.length!==2) {alert('Prima riga non valida: cartella|replace oppure cartella|rename.');return;}
        var mode=trim(first[1]).toLowerCase();
        if(mode!=='replace' && mode!=='rename') {alert('Modalita attesa: replace oppure rename.');return;}
        pathInput.text=trim(first[0]);replace.value=(mode==='replace');rename.value=!replace.value;
    };
    exportButton.onClick=function() {
        try {
            var content=String(rawInput.text);
            configParse(content); // valida prima di chiudere
            if(!confirm('Avviare la coda di esportazione PDF?'))return;
            w.close(1);
            runQueue(content);
        } catch(e) {alert('Configurazione non valida:\n'+e);}
    };
    cancelButton.onClick=function(){w.close(0);};
    w.center();w.show();
})();
