/**
 * Letras Recortadas (Bigger Title Support)
 * Desenvolvido para Adobe After Effects
 */

(function(thisObj) {
    // ==========================================
    // 1. INTERFACE DO USUÁRIO
    // ==========================================
    function buildUI(thisObj) {
        var win = (thisObj instanceof Panel) ? thisObj : new Window("palette", "Letras Recortadas", undefined, {resizeable:true});
        win.orientation = "column";
        win.alignChildren = ["fill", "top"];
        win.spacing = 10;
        win.margins = 12;

        var scriptFile = new File($.fileName);
        var scriptFolder = scriptFile.parent.fsName;
        var defaultAssetsFolder = new Folder(scriptFolder + "/ASSETS/LETRAS RECORTADAS");
        var selectedFolder = defaultAssetsFolder.exists ? defaultAssetsFolder : null;

        // --- CABEÇALHO VISUAL ---
        var grpVisualHeader = win.add("group");
        grpVisualHeader.orientation = "column";
        grpVisualHeader.alignChildren = ["center", "center"];
        grpVisualHeader.alignment = ["fill", "top"];
        grpVisualHeader.spacing = 0;
        grpVisualHeader.margins = [0, 10, 0, 10]; 

        var titlePngFile = new File(scriptFolder + "/ASSETS/LETRAS RECORTADAS/titulo_letras.png");
        var uiTitle;

        if (titlePngFile.exists) {
            uiTitle = grpVisualHeader.add("image", undefined, titlePngFile);
            uiTitle.alignment = ["center", "center"];
        } else {
            uiTitle = grpVisualHeader.add("statictext", undefined, "LETRAS RECORTADAS");
            uiTitle.graphics.font = ScriptUI.newFont("Arial", "BOLD", 20);
            var uiSubTitle = grpVisualHeader.add("statictext", undefined, "GERADOR V3.2");
            uiSubTitle.graphics.font = ScriptUI.newFont("Arial", "REGULAR", 11);
            uiSubTitle.graphics.foregroundColor = uiSubTitle.graphics.newPen(win.graphics.PenType.SOLID_COLOR, [0.5, 0.5, 0.5], 1);
        }

        var dividerTop = win.add("panel", undefined, "");
        dividerTop.minimumSize.height = 2; dividerTop.alignment = "fill";

        // --- STATUS ---
        var grpTop = win.add("group");
        grpTop.orientation = "row";
        grpTop.alignChildren = ["left", "center"];
        var txtStatus = grpTop.add("statictext", undefined, selectedFolder ? "● Assets Conectados" : "○ Assets Não Encontrados");
        txtStatus.graphics.foregroundColor = txtStatus.graphics.newPen(win.graphics.PenType.SOLID_COLOR, selectedFolder ? [0.3, 0.7, 0.3] : [0.8, 0.3, 0.3], 1);
        
        var btnSelectFolder = grpTop.add("button", undefined, "Procurar Pasta");
        btnSelectFolder.visible = !selectedFolder;

        // --- TEXTO ---
        var txtLabel = win.add("statictext", undefined, "Texto (Comp deve estar aberta):");
        var edtText = win.add("edittext", undefined, "DIGITE AQUI", {multiline: true});
        edtText.minimumSize.height = 60;

        // --- ESPAÇAMENTO E ALINHAMENTO ---
        var grpSpacing = win.add("group");
        grpSpacing.orientation = "row";
        grpSpacing.alignChildren = ["left", "center"];
        grpSpacing.spacing = 15;
        grpSpacing.add("statictext", undefined, "Espaço (px):");
        var numKerning = grpSpacing.add("edittext", undefined, "200");
        numKerning.characters = 4;
        var ddAlign = grpSpacing.add("dropdownlist", undefined, ["Esquerda", "Centro", "Direita"]);
        ddAlign.selection = 1;

        var divider = win.add("panel", undefined, "");
        divider.minimumSize.height = 2; divider.alignment = "fill";

        // --- ESTÉTICA E CAOS ---
        var grpScale = win.add("group");
        grpScale.orientation = "row";
        grpScale.alignChildren = ["left", "center"];
        grpScale.add("statictext", undefined, "Escala Aleatória (%):");
        var numMinScale = grpScale.add("edittext", undefined, "100"); numMinScale.characters = 3;
        grpScale.add("statictext", undefined, "a");
        var numMaxScale = grpScale.add("edittext", undefined, "100"); numMaxScale.characters = 3;

        var grpYShadow = win.add("group");
        grpYShadow.orientation = "row";
        grpYShadow.alignChildren = ["left", "center"];
        grpYShadow.spacing = 15;
        grpYShadow.add("statictext", undefined, "Desalinhamento Y:");
        var numYJitter = grpYShadow.add("edittext", undefined, "0"); numYJitter.characters = 3;
        var cbShadow = grpYShadow.add("checkbox", undefined, "Sombra");
        cbShadow.value = false;

        var divider1_5 = win.add("panel", undefined, "");
        divider1_5.minimumSize.height = 2; divider1_5.alignment = "fill";

        // --- TROCA AUTOMÁTICA ---
        var grpSettings = win.add("group");
        grpSettings.orientation = "row";
        grpSettings.alignChildren = ["left", "center"];
        grpSettings.spacing = 12;
        var cbAutoSwap = grpSettings.add("checkbox", undefined, "Troca Auto");
        cbAutoSwap.value = true;
        var cbDesync = grpSettings.add("checkbox", undefined, "Desincronizar");
        cbDesync.value = true;
        var grpRate = win.add("group");
        grpRate.orientation = "row";
        grpRate.alignChildren = ["left", "center"];
        grpRate.spacing = 5;
        grpRate.add("statictext", undefined, "Parar por (frames):");
        var numFramesHold = grpRate.add("edittext", undefined, "36"); 
        numFramesHold.characters = 3;

        cbAutoSwap.onClick = function() { grpRate.enabled = cbAutoSwap.value; cbDesync.enabled = cbAutoSwap.value; };

        var divider2 = win.add("panel", undefined, "");
        divider2.minimumSize.height = 2; divider2.alignment = "fill";

        // --- WIGGLE ---
        var cbWiggle = win.add("checkbox", undefined, "Aplicar Tremor (Wiggle)");
        cbWiggle.value = true;
        var grpWiggle = win.add("group");
        grpWiggle.orientation = "row";
        grpWiggle.alignChildren = ["left", "center"];
        grpWiggle.spacing = 10;
        grpWiggle.add("statictext", undefined, "Freq:");
        var numWigFreq = grpWiggle.add("edittext", undefined, "4");
        numWigFreq.characters = 3;
        grpWiggle.add("statictext", undefined, "Pos:");
        var numWigPos = grpWiggle.add("edittext", undefined, "15");
        numWigPos.characters = 3;
        grpWiggle.add("statictext", undefined, "Rot:");
        var numWigRot = grpWiggle.add("edittext", undefined, "5");
        numWigRot.characters = 3;
        cbWiggle.onClick = function() { grpWiggle.enabled = cbWiggle.value; };
        cbWiggle.onClick(); 

        // --- BOTÃO GERAR ---
        var btnGenerate = win.add("button", undefined, "Gerar Composição");
        btnGenerate.minimumSize.height = 35;

        // --- RODAPÉ ---
        var divider3 = win.add("panel", undefined, "");
        divider3.minimumSize.height = 2; divider3.alignment = "fill";
        var grpFooter = win.add("group");
        grpFooter.orientation = "row";
        grpFooter.alignChildren = ["center", "center"];
        grpFooter.alignment = ["fill", "bottom"];
        
        var logoFile = new File(scriptFolder + "/nandomp4_logo_32.png");
        var myLogo;
        if (logoFile.exists) { 
            myLogo = grpFooter.add("image", undefined, logoFile); 
        } else {
            myLogo = grpFooter.add("statictext", undefined, "nando.mp4");
            myLogo.graphics.font = ScriptUI.newFont("Arial", "BOLD", 14);
            myLogo.graphics.foregroundColor = myLogo.graphics.newPen(win.graphics.PenType.SOLID_COLOR, [0.9, 0.7, 0.1], 1);
        }
        myLogo.helpTip = "Visite nandomp4.com";
        myLogo.addEventListener("mousedown", function() {
            var url = "https://www.nandomp4.com/scripts";
            if ($.os.indexOf("Windows") !== -1) { system.callSystem("cmd.exe /c \"start " + url + "\""); } else { system.callSystem("open \"" + url + "\""); }
        });

        // --- EVENTOS ---
        btnSelectFolder.onClick = function() {
            var f = Folder.selectDialog("Selecione a pasta 'LETRAS RECORTADAS'");
            if (f) {
                selectedFolder = f;
                txtStatus.text = "● Assets Conectados";
                txtStatus.graphics.foregroundColor = txtStatus.graphics.newPen(win.graphics.PenType.SOLID_COLOR, [0.3, 0.7, 0.3], 1);
                btnSelectFolder.visible = false;
                win.layout.layout(true);
            }
        };

        btnGenerate.onClick = function() {
            if (!selectedFolder) { alert("Pasta de Assets ausente."); return; }
            if (edtText.text === "") { alert("Digite algum texto."); return; }
            var params = { 
                text: edtText.text, 
                kerning: parseFloat(numKerning.text) || 200, 
                align: ddAlign.selection.index, 
                minScale: parseFloat(numMinScale.text) || 100, 
                maxScale: parseFloat(numMaxScale.text) || 100, 
                yJitter: parseFloat(numYJitter.text) || 0, 
                shadow: cbShadow.value, 
                autoSwap: cbAutoSwap.value, 
                desync: cbDesync.value, 
                holdFrames: Math.max(1, parseInt(numFramesHold.text) || 36), 
                wiggle: cbWiggle.value, 
                wFreq: parseFloat(numWigFreq.text) || 4, 
                wPos: parseFloat(numWigPos.text) || 15, 
                wRot: parseFloat(numWigRot.text) || 5 
            };
            generateRansomNoteV2(selectedFolder, params);
        };

        win.layout.layout(true);
        win.onResizing = win.onResize = function() { this.layout.resize(); };
        return win;
    }

    // ==========================================
    // 2. LÓGICA DE GERAÇÃO
    // ==========================================
    function generateRansomNoteV2(assetsFolder, p) {
        app.beginUndoGroup("Gerar Ransom Note V3.2");
        try {
            var proj = app.project;
            var mainComp = proj.activeItem;
            if (!mainComp || !(mainComp instanceof CompItem)) { alert("Selecione uma comp ativa."); return; }
            var mainBin = createOrFindFolder(proj, "Letras_Recortadas_");

            var lines = p.text.split(/[\r\n]+/);
            var leading = p.kerning * 1.5;

            var nullLayer = mainComp.layers.addNull();
            nullLayer.name = "cntrl_geral"; 
            if (nullLayer.source) {
                nullLayer.source.name = "cntrl_geral"; 
            }
            nullLayer.property("Anchor Point").setValue([0, 0]);
            nullLayer.property("Position").setValue([mainComp.width / 2, mainComp.height / 2]);

            var validLines = [];
            for (var l = 0; l < lines.length; l++) {
                var lineText = lines[l];
                if (lineText.length === 0) continue;

                var validElements = [];
                for (var c = 0; c < lineText.length; c++) {
                    var rawChar = lineText.charAt(c);
                    if (rawChar === " ") {
                        validElements.push({type: "space"});
                        continue;
                    }
                    var folderName = getSafeFolderName(rawChar);
                    var charFolder = new Folder(assetsFolder.fsName + "/" + folderName);
                    if (!charFolder.exists) { charFolder = new Folder(assetsFolder.fsName + "/" + getSafeFolderName(rawChar.toUpperCase())); }
                    if (!charFolder.exists) continue;

                    var files = charFolder.getFiles("*.png");
                    if (files.length === 0) continue;

                    validElements.push({type: "letter", caractere_real: rawChar, files: files});
                }
                if (validElements.length > 0) {
                    validLines.push(validElements);
                }
            }

            if (validLines.length === 0) {
                alert("Nenhuma letra correspondente encontrada na pasta.");
                nullLayer.remove();
                return;
            }

            var blockHeight = (validLines.length - 1) * leading;
            var startY = -blockHeight / 2; 

            // ==========================================
            // NOVO SISTEMA DE CACHE INTELIGENTE
            // ==========================================
            // Varre o projeto inteiro ANTES de importar e armazena os arquivos
            // que já foram carregados previamente no painel Project.
            var importedCache = {}; 
            for (var i = 1; i <= proj.numItems; i++) {
                var projItem = proj.item(i);
                try {
                    // Confirma se é uma footage válida e possui arquivo vinculado
                    if (projItem instanceof FootageItem && projItem.mainSource && projItem.mainSource.file) {
                        importedCache[projItem.mainSource.file.fsName] = projItem;
                    }
                } catch(e) {
                    // Silencia erro caso existam itens ausentes/corrompidos no projeto
                }
            }

            for (var m = 0; m < validLines.length; m++) {
                var els = validLines[m];
                var lineWidth = (els.length - 1) * p.kerning;

                var startX = 0;
                if (p.align === 1) { 
                    startX = -lineWidth / 2;
                } else if (p.align === 0) { 
                    var marginX = mainComp.width * 0.1;
                    startX = marginX - (mainComp.width / 2);
                } else if (p.align === 2) { 
                    var marginXRight = mainComp.width * 0.1;
                    startX = (mainComp.width / 2) - marginXRight - lineWidth;
                }

                var currentX = startX;
                var currentY = startY + (m * leading);

                for (var e = 0; e < els.length; e++) {
                    var el = els[e];
                    if (el.type === "space") {
                        currentX += p.kerning;
                        continue;
                    }

                    var targetLayer = null;
                    
                    var importedItems = [];
                    for (var j = 0; j < el.files.length; j++) {
                        var fileKey = el.files[j].fsName;
                        var itm = importedCache[fileKey];
                        if (!itm) {
                            itm = importAsset(el.files[j], mainBin);
                            if (itm) importedCache[fileKey] = itm;
                        }
                        if (itm) importedItems.push(itm);
                    }

                    if (!p.autoSwap) {
                        if (importedItems.length > 0) {
                            var randomItm = importedItems[Math.floor(Math.random() * importedItems.length)];
                            targetLayer = mainComp.layers.add(randomItm);
                        }
                    } else {
                        if (importedItems.length > 0) {
                            var preCompW = importedItems[0].width;
                            var preCompH = importedItems[0].height;
                            
                            var preComp = proj.items.addComp("Letra_" + el.caractere_real + "_Comp", preCompW, preCompH, mainComp.pixelAspect, mainComp.duration, mainComp.frameRate);
                            preComp.parentFolder = mainBin;
                            
                            var randomOffset = p.desync ? Math.floor(Math.random() * 100) : 0;
                            var uniqueSeed = Math.floor(Math.random() * 100000);
                            
                            var expr = "var holdFrames = " + p.holdFrames + ";\n" +
                                       "var currentFrame = Math.round(time / thisComp.frameDuration) + " + randomOffset + ";\n" +
                                       "var step = Math.floor(currentFrame / holdFrames);\n" +
                                       "var seed = Math.abs(step * 12345 + " + uniqueSeed + ");\n" +
                                       "var r = ((seed * 9301 + 49297) % 233280) / 233280;\n" +
                                       "var target = Math.floor(r * thisComp.numLayers) + 1;\n" +
                                       "(index == target) ? 100 : 0;";

                            for (var k = 0; k < importedItems.length; k++) {
                                var sL = preComp.layers.add(importedItems[k]);
                                sL.property("Position").setValue([preCompW/2, preCompH/2]); 
                                sL.property("Scale").setValue([100, 100]); // TRAVA DE SEGURANÇA NA PRE-COMP
                                sL.property("Opacity").expression = expr; 
                            }
                            targetLayer = mainComp.layers.add(preComp);
                        }
                    }

                    if (targetLayer !== null) {
                        targetLayer.parent = nullLayer;

                        var yOffset = (Math.random() * (p.yJitter * 2)) - p.yJitter;
                        targetLayer.property("Position").setValue([currentX, currentY + yOffset]);
                        
                        // APLICAÇÃO DE ESCALA SEGURA NA COMP PRINCIPAL
                        var s = p.minScale + Math.random() * (p.maxScale - p.minScale); 
                        targetLayer.property("Scale").setValue([s, s]);
                        
                        if (p.shadow) { 
                            var ds = targetLayer.Effects.addProperty("ADBE Drop Shadow"); 
                            ds.property("Distance").setValue(15); 
                            ds.property("Softness").setValue(25); 
                            ds.property("Opacity").setValue(127); 
                        }
                        if (p.wiggle) { 
                            targetLayer.property("Position").expression = "posterizeTime(" + p.wFreq + "); wiggle(" + p.wFreq + ", " + p.wPos + ");"; 
                            targetLayer.property("Rotation").expression = "posterizeTime(" + p.wFreq + "); wiggle(" + p.wFreq + ", " + p.wRot + ");"; 
                        }
                    }
                    currentX += p.kerning;
                }
            }
        } catch (err) { alert("Erro: " + err.toString()); } finally { app.endUndoGroup(); }
    }

    // ==========================================
    // 3. FUNÇÕES AUXILIARES
    // ==========================================
    function importAsset(f, d) { try { var io = new ImportOptions(f); io.sequence = false; var i = app.project.importFile(io); i.parentFolder = d; return i; } catch(e) {} return null; }
    function createOrFindFolder(p, n) { for (var i = 1; i <= p.numItems; i++) { if (p.item(i) instanceof FolderItem && p.item(i).name === n) return p.item(i); } return p.items.addFolder(n); }
    function getSafeFolderName(s) { var m = { "?": "interrogacao", "!": "exclamacao", ".": "ponto", ",": "virgula", ":": "dois_pontos", "/": "barra", "\\": "barra_invertida", "*": "asterisco", "\"": "aspas", "<": "menor_que", ">": "maior_que", "|": "pipe" }; return m[s] || s; }

    var myPanel = buildUI(thisObj);
    if ((myPanel != null) && (myPanel instanceof Window)) { myPanel.center(); myPanel.show(); }
})(this);