package cz.kamma.llamarunner;

import java.io.Serializable;

/**
 * Class for storing llama-server configuration.
 */
public class ModelConfig implements Serializable {
    private static final long serialVersionUID = 1L;
    private static final int DEFAULT_BATCH_SIZE = 4096;

    private String host;
    private int port;
    private int parallel;
    private int batchSize;
    private int threads;
    private boolean flashAttention;
    private boolean kvUnified;
    private String cacheTypeK;
    private String cacheTypeV;
    private double temperature;
    private double topP;
    private int topK;
    private double minP;
    private int ctxSize;
    private boolean enableThinking;
    private String modelPath;
    private String mmprojPath;
    private String chatTemplateKwargs;
    private int ngl;
    private boolean fit;
    private boolean reasoning;

    public ModelConfig() {
        this.host = "0.0.0.0";
        this.port = 3080;
        this.parallel = 1;
        this.batchSize = DEFAULT_BATCH_SIZE;
        this.threads = 99;
        this.flashAttention = true;
        this.kvUnified = true;
        this.cacheTypeK = "q8_0";
        this.cacheTypeV = "q8_0";
        this.temperature = 0.6;
        this.topP = 0.95;
        this.topK = 20;
        this.minP = 0.00;
        this.ctxSize = 180000;
        this.enableThinking = false;
        this.modelPath = "";
        this.mmprojPath = "";
        this.chatTemplateKwargs = "";
        this.ngl = 999;
        this.fit = false;
        this.reasoning = false;
    }

    // Getters and setters
    public String getHost() { return host; }
    public void setHost(String host) { this.host = host; }

    public int getPort() { return port; }
    public void setPort(int port) { this.port = port; }

    public int getParallel() { return parallel; }
    public void setParallel(int parallel) { this.parallel = parallel; }

    public int getBatchSize() { return batchSize > 0 ? batchSize : DEFAULT_BATCH_SIZE; }
    public void setBatchSize(int batchSize) { this.batchSize = batchSize; }

    public int getThreads() { return threads; }
    public void setThreads(int threads) { this.threads = threads; }

    public boolean isFlashAttention() { return flashAttention; }
    public void setFlashAttention(boolean flashAttention) { this.flashAttention = flashAttention; }

    public boolean isKvUnified() { return kvUnified; }
    public void setKvUnified(boolean kvUnified) { this.kvUnified = kvUnified; }

    public String getCacheTypeK() { return cacheTypeK; }
    public void setCacheTypeK(String cacheTypeK) { this.cacheTypeK = cacheTypeK; }

    public String getCacheTypeV() { return cacheTypeV; }
    public void setCacheTypeV(String cacheTypeV) { this.cacheTypeV = cacheTypeV; }

    public double getTemperature() { return temperature; }
    public void setTemperature(double temperature) { this.temperature = temperature; }

    public double getTopP() { return topP; }
    public void setTopP(double topP) { this.topP = topP; }

    public int getTopK() { return topK; }
    public void setTopK(int topK) { this.topK = topK; }

    public double getMinP() { return minP; }
    public void setMinP(double minP) { this.minP = minP; }

    public int getCtxSize() { return ctxSize; }
    public void setCtxSize(int ctxSize) { this.ctxSize = ctxSize; }

    public boolean isEnableThinking() { return enableThinking; }
    public void setEnableThinking(boolean enableThinking) { this.enableThinking = enableThinking; }

    public String getModelPath() { return modelPath; }
    public void setModelPath(String modelPath) { this.modelPath = modelPath; }

    public String getMmprojPath() { return mmprojPath; }
    public void setMmprojPath(String mmprojPath) { this.mmprojPath = mmprojPath; }

    public String getChatTemplateKwargs() { return chatTemplateKwargs; }
    public void setChatTemplateKwargs(String chatTemplateKwargs) { this.chatTemplateKwargs = chatTemplateKwargs; }

    public int getNgl() { return ngl; }
    public void setNgl(int ngl) { this.ngl = ngl; }

    public boolean isFit() { return fit; }
    public void setFit(boolean fit) { this.fit = fit; }

    public boolean isReasoning() { return reasoning; }
    public void setReasoning(boolean reasoning) { this.reasoning = reasoning; }

    @Override
    public String toString() {
        return "ModelConfig{" +
                "host='" + host + '\'' +
                ", port=" + port +
                ", parallel=" + parallel +
                ", batchSize=" + getBatchSize() +
                ", threads=" + threads +
                ", flashAttention=" + flashAttention +
                ", kvUnified=" + kvUnified +
                ", cacheTypeK='" + cacheTypeK + '\'' +
                ", cacheTypeV='" + cacheTypeV + '\'' +
                ", temperature=" + temperature +
                ", topP=" + topP +
                ", topK=" + topK +
                ", minP=" + minP +
                ", ctxSize=" + ctxSize +
                ", enableThinking=" + enableThinking +
                ", modelPath='" + modelPath + '\'' +
                ", mmprojPath='" + mmprojPath + '\'' +
                ", chatTemplateKwargs='" + chatTemplateKwargs + '\'' +
                ", ngl=" + ngl +
                ", fit=" + fit +
                ", reasoning=" + reasoning +
                '}';
    }
}
