from models.S3VM_constrained import S3VM_Constrained
from models.S3VM_unconstrained import S3VM_Unconstrained
from models.NewtonUTSVM import NewtonUTSVM
from models.TSVM import TSVM
from models.LSTSVM import LSTSVM
from models.utils import load_dataset


MODELS = [
    "Semi-Supervised_SVM",
    "Semi-Supervised_SVM_Unconstrained",
    "Newton_Universum_Twin_SVM",
    "Least-Square_Twin_SVM",
    "Twin_SVM"
]


def runner(model, dataset, params):

    csv_file = f"datasets/{dataset}.csv"
    x_train, y_train, x_test, y_test, U  = load_dataset(csv_file)
    accuracy = 0

    print('model: ', model)

    match model:

        case "Semi-Supervised_SVM":

            C = params['C'] or 1.0
            max_iter = params.get('max_iter') or 100

            modelObj = S3VM_Constrained(C, max_iter)
            modelObj.fit(x_train, y_train, U)
            modelObj.predict(x_test)
            accuracy = modelObj.score(y_test)
            params = {"C": C, "max_iter": max_iter}

        case "Semi-Supervised_SVM_Unconstrained":

            C = params['C'] or 1.0

            modelObj = S3VM_Unconstrained(C)
            modelObj.fit(x_train, y_train, U)
            modelObj.predict(x_test)
            accuracy = modelObj.score(y_test)
            params = {"C": C}

        case "Newton_Universum_Twin_SVM":

            C = params['C'] or [1.0, 1.0, 1.0, 1.0, 1.0, 1.0]

            modelObj = NewtonUTSVM(x_train, y_train, U, C)
            modelObj.fit()
            modelObj.predict(x_test)
            accuracy = modelObj.score(y_test)
            params = {"C": C}

        case "Least-Square_Twin_SVM":

            C = params['C'] or [1.0, 1.0]

            modelObj = LSTSVM(x_train, y_train, C[0], C[1])
            modelObj.fit()
            modelObj.predict(x_test, y_test)
            accuracy = modelObj.score(y_test)
            params = {"C": C}

        case "Twin_SVM":

            C = params['C'] or [1.0, 1.0]

            modelObj = TSVM(x_train, y_train, C[0], C[1])
            modelObj.fit()
            modelObj.predict(x_test)
            accuracy = modelObj.score(y_test)
            params = {"C": C}


    accuracy = round(accuracy, 4)

    return {
        "model":model,
        "dataset":dataset,
        "params": params,
        "accuracy": accuracy
        }

            




