//@script "Layer Sequence"
//@target illustrator
//@targetengine 'main'
//@strict on
// Last Edit: 2020-10-23

var W;

function btMsg(a, getResult) {
    var getResult = typeof getResult === "boolean" ? getResult : false;
    var bt = new BridgeTalk();
    bt.target = "illustrator";
    bt.body = a;
    bt.onResult = getResult ? function(msg) {
        var event = new Event('btMsgResult');
        event.result = msg;
        W.dispatchEvent(event);
    } : undefined;
    bt.onError = function(err) {
        alert(err.body + "(" + err.headers["Error-Code"] + ")");
    };
    bt.send();
}

function showLayer(layerDelta, defaultLayerIdx) {
    var defaultLayerIdx = typeof defaultLayerIdx === "number" ? defaultLayerIdx : 0;
    var layerArray = app.activeDocument.layers;
    var currentIdx = -1;
    for (var i = 0; i < layerArray.length; i++) {
        if (layerArray[i].visible) {
            currentIdx = i;
            break;
        }
    }
    // If no layer is visible, just set to default
    if (currentIdx < 0) {
        currentIdx = defaultLayerIdx;
    }
    var output = {
        total: layerArray.length,
        current: currentIdx
    }
    var nextIdx = currentIdx + layerDelta;
    // If we're past the array indices, loop around
    if (nextIdx < 0) {
        nextIdx = layerArray.length - 1;
    }
    if (nextIdx >= layerArray.length) {
        nextIdx = 0;
    }
    output.current = nextIdx;
    // Turn off all layers
    for (var i = 0; i < layerArray.length; i++) {
        layerArray[i].visible = false;
    }
    // Turn on the selected layer
    layerArray[nextIdx].visible = true;
    // The result sent via BridgeTalk must be a string
    return output.toSource();
}

function LayerSequenceWindow() {
    var WINDOW_TYPE = "palette";
    var WINDOW_NAME = "Layer Sequence";
    if (!W) {
        W = Window.find(WINDOW_TYPE, WINDOW_NAME);
    }

    // Destroy the window if it exists
    if (W) {
        W.visible && W.close();
        W = null;
        delete W;
    }

    this.createWindow = function() {
        W = new Window(WINDOW_TYPE, WINDOW_NAME);
        var pnlSeq = W.add("panel");
        pnlSeq.orientation = "row";
        
        // Get the currently active layer index
        var activeLayer = app.activeDocument.activeLayer;
        var activeIdx = 0;
        var layerArray = app.activeDocument.layers;
        for (var i = 0; i < layerArray.length; i++) {
            if (layerArray[i] == activeLayer) {
                activeIdx = i;
                $.writeln("Found active layer index: " + i);
                break;
            }
        }
        
        // The forward and back buttons
        var btnGrp = W.add("group");
        btnGrp.orientation = "row";
        var btnBackward = btnGrp.add("button", undefined, "<");
        btnBackward.maximumSize = [40, 30];
        btnBackward.helpTip = "Move backward in the sequence (Keyboard: Left)";
        var btnForward = btnGrp.add("button", undefined, ">");
        btnForward.maximumSize = [40, 30];
        btnForward.helpTip = "Move forward in the sequence (Keyboard: Right)";

        // Helper function that formats the call to BridgeTalk and allows us to
        // change the sequence number by delta. For example, to go forward one
        // number in the sequence, delta would be equal to 1.
        function deltaSequence(delta) {
            // Use the btMsg function to send our function to Illustrator. 
            // See the btMsg declaration for more info.
            btMsg(
                showLayer.toString()
                + ";showLayer(" 
                + delta + ", " + activeIdx + ");"
            );
            btMsg("app.redraw();");
        }

        // If you click the forward button
        btnForward.onClick = function() {
            deltaSequence(1);
        }
        
        // If you click the backward button you do similar stuff as above.
        btnBackward.onClick = function() {
            deltaSequence(-1)
        }
        
        // Keyboard event listener
        W.addEventListener("keydown", function(e){
            e.preventDefault();
            switch(e.keyName) {
                case "Right":
                case "Down":
                    deltaSequence(1);
                    break;
                case "Left":
                case "Up":
                    deltaSequence(-1);
                    break;
            }
        });
        
        W.onShow = function() {
            // Turn all layers off
            for (var i = 0; i < layerArray.length; i++) {
                layerArray[i].visible = false;
            }
            // Turn on the currently active layer
            layerArray[activeIdx].visible = true;
        };

        // Show the window if it isn't visible already
        W.visible || W.show();
    };

    // Create the window
    if (!W) {
        this.createWindow();
    }
};

LayerSequenceWindow();