package io.xpipe.app.terminal;

import io.xpipe.app.process.*;

import com.fasterxml.jackson.annotation.JsonTypeName;
import lombok.Builder;
import lombok.extern.jackson.Jacksonized;

import java.util.ArrayList;

@Builder
@Jacksonized
@JsonTypeName("screen")
public class ScreenTerminalMultiplexer implements TerminalMultiplexer {

    @Override
    public boolean supportsSplitView() {
        return false;
    }

    @Override
    public String getDocsLink() {
        return "https://www.gnu.org/software/screen/manual/screen.html";
    }

    @Override
    public boolean shouldSelect() {
        return false;
    }

    @Override
    public void checkSupported(ShellControl sc) throws Exception {
        CommandSupport.isInPathOrThrow(sc, "screen");
    }

    @Override
    public ShellScript launchForExistingSession(ShellControl control, TerminalLaunchConfiguration config) {
        var l = new ArrayList<String>();
        var firstCommand =
                getCommand(control, config.single().getDialectLaunchCommand().buildSimple());
        l.add("screen -S xpipe -X screen -t \"" + escape(config.getCleanTitle(), true) + "\" "
                + escape(firstCommand, false));
        return ShellScript.lines(l);
    }

    @Override
    public ShellScript launchNewSession(ShellControl control, TerminalLaunchConfiguration config) {
        var list = new ArrayList<String>();
        list.add("for scr in $(screen -ls | grep xpipe | awk '{print $1}'); do screen -S $scr -X quit; done");

        var firstCommand =
                getCommand(control, config.single().getDialectLaunchCommand().buildSimple());
        list.add("screen -S xpipe -t \"" + escape(config.getCleanTitle(), true) + "\" " + escape(firstCommand, false));
        return ShellScript.lines(list);
    }

    private String getCommand(ShellControl sc, String command) {
        // Screen has a limit of 100 chars for commands
        var effectiveCommand = command.length() > 90
                ? ScriptHelper.createExecScript(sc, command).toString()
                : command;
        return effectiveCommand;
    }

    private String escape(String s, boolean quotes) {
        var r = s.replaceAll("\\\\", "\\\\\\\\");
        if (quotes) {
            r = r.replaceAll("\"", "\\\\\"");
        }
        return r;
    }
}
