package io.xpipe.app.terminal;

import io.xpipe.app.core.AppI18n;
import io.xpipe.app.core.mode.AppOperationMode;
import io.xpipe.app.issue.ErrorEventFactory;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.app.process.CommandControl;
import io.xpipe.app.process.LocalShell;
import io.xpipe.app.process.ProcessControl;
import io.xpipe.app.process.ShellControl;
import io.xpipe.app.process.ShellScript;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.storage.DataStoreEntry;
import io.xpipe.app.util.FailableFunction;
import io.xpipe.app.util.FilePath;

import lombok.Builder;
import lombok.Value;

import java.util.List;
import java.util.UUID;

@Value
@Builder
public class TerminalLaunch {

    DataStoreEntry entry;
    String title;
    FilePath directory;
    ProcessControl command;
    UUID request;

    @Builder.Default
    boolean preferTabs = true;

    @Builder.Default
    boolean logIfEnabled = true;

    @Builder.Default
    boolean pauseOnExit = AppPrefs.get().terminalAlwaysPauseOnExit().getValue();

    ExternalTerminalType terminal;

    public String getFullTitle() {
        return entry != null
                ? (title != null ? title + " - " : "") + DataStorage.get().getStoreEntryDisplayName(entry)
                : title != null ? title : "";
    }

    public void launch() throws Exception {
        var type = AppPrefs.get().terminalType().getValue();
        if (type == null) {
            throw ErrorEventFactory.expected(new IllegalStateException(AppI18n.get("noTerminalSet")));
        }

        if (AppOperationMode.get() == null) {
            if (command instanceof CommandControl cc) {
                TerminalLauncher.openDirect(
                        getFullTitle(),
                        sc -> new ShellScript(cc.getTerminalCommand().buildFull(sc)),
                        ExternalTerminalType.determineFallbackTerminalToOpen(type));
            }
            return;
        }

        var pane = new TerminalLauncher.Config(
                entry,
                getFullTitle(),
                directory,
                request != null ? request : UUID.randomUUID(),
                logIfEnabled,
                pauseOnExit,
                command);
        TerminalLauncher.open(List.of(pane), preferTabs, type);
    }

    public static class TerminalLaunchBuilder {

        public void launch() throws Exception {
            var l = build();
            l.launch();
        }

        public TerminalLaunchBuilder localScript(ShellScript script) {
            var c = LocalShell.getShell().command(script);
            return command(c);
        }

        public TerminalLaunchBuilder localScript(FailableFunction<ShellControl, ShellScript, Exception> script)
                throws Exception {
            var c = LocalShell.getShell().command(script.apply(LocalShell.getShell()));
            return command(c);
        }
    }
}
