# include "pmModelGroup.h"

double hypot(double x, double y);
double sqrt (double x);

#include "psEllipse.h"
#include "models/pmModel_GAUSS.c"
#include "models/pmModel_PGAUSS.c"
#include "models/pmModel_QGAUSS.c"
#include "models/pmModel_SGAUSS.c"

static pmModelGroup models[] = {
                                   {"PS_MODEL_GAUSS",        7, pmModelFunc_GAUSS,   pmModelFlux_GAUSS,   pmModelRadius_GAUSS,   pmModelLimits_GAUSS,   pmModelGuess_GAUSS,  pmModelFromPSF_GAUSS,  pmModelFitStatus_GAUSS},
                                   {"PS_MODEL_PGAUSS",       7, pmModelFunc_PGAUSS,  pmModelFlux_PGAUSS,  pmModelRadius_PGAUSS,  pmModelLimits_PGAUSS,  pmModelGuess_PGAUSS, pmModelFromPSF_PGAUSS, pmModelFitStatus_PGAUSS},
                                   {"PS_MODEL_QGAUSS",       8, pmModelFunc_QGAUSS,  pmModelFlux_QGAUSS,  pmModelRadius_QGAUSS,  pmModelLimits_QGAUSS,  pmModelGuess_QGAUSS, pmModelFromPSF_QGAUSS, pmModelFitStatus_QGAUSS},
                                   {"PS_MODEL_SGAUSS",       9, pmModelFunc_SGAUSS,  pmModelFlux_SGAUSS,  pmModelRadius_SGAUSS,  pmModelLimits_SGAUSS,  pmModelGuess_SGAUSS, pmModelFromPSF_SGAUSS, pmModelFitStatus_SGAUSS},
                               };

pmModelFunc pmModelFunc_GetFunction (pmModelType type)
{
    int Nmodels = sizeof (models) / sizeof (pmModelGroup);
    if ((type < 0) || (type >= Nmodels)) {
        psError(PS_ERR_UNKNOWN, true, "Undefined pmModelType");
        return (NULL);
    }
    return (models[type].modelFunc);
}

pmModelFlux pmModelFlux_GetFunction (pmModelType type)
{
    int Nmodels = sizeof (models) / sizeof (pmModelGroup);
    if ((type < 0) || (type >= Nmodels)) {
        psError(PS_ERR_UNKNOWN, true, "Undefined pmModelType");
        return (NULL);
    }
    return (models[type].modelFlux);
}

pmModelRadius pmModelRadius_GetFunction (pmModelType type)
{
    int Nmodels = sizeof (models) / sizeof (pmModelGroup);
    if ((type < 0) || (type >= Nmodels)) {
        psError(PS_ERR_UNKNOWN, true, "Undefined pmModelType");
        return (NULL);
    }
    return (models[type].modelRadius);
}

pmModelLimits pmModelLimits_GetFunction (pmModelType type)
{
    int Nmodels = sizeof (models) / sizeof (pmModelGroup);
    if ((type < 0) || (type >= Nmodels)) {
        psError(PS_ERR_UNKNOWN, true, "Undefined pmModelType");
        return (NULL);
    }
    return (models[type].modelLimits);
}

pmModelGuessFunc pmModelGuessFunc_GetFunction (pmModelType type)
{
    int Nmodels = sizeof (models) / sizeof (pmModelGroup);
    if ((type < 0) || (type >= Nmodels)) {
        psError(PS_ERR_UNKNOWN, true, "Undefined pmModelType");
        return (NULL);
    }
    return (models[type].modelGuessFunc);
}

pmModelFitStatusFunc pmModelFitStatusFunc_GetFunction (pmModelType type)
{
    int Nmodels = sizeof (models) / sizeof (pmModelGroup);
    if ((type < 0) || (type >= Nmodels)) {
        psError(PS_ERR_UNKNOWN, true, "Undefined pmModelType");
        return (NULL);
    }
    return (models[type].modelFitStatusFunc);
}

pmModelFromPSFFunc pmModelFromPSFFunc_GetFunction (pmModelType type)
{
    int Nmodels = sizeof (models) / sizeof (pmModelGroup);
    if ((type < 0) || (type >= Nmodels)) {
        psError(PS_ERR_UNKNOWN, true, "Undefined pmModelType");
        return (NULL);
    }
    return (models[type].modelFromPSFFunc);
}

psS32 pmModelParameterCount (pmModelType type)
{
    int Nmodels = sizeof (models) / sizeof (pmModelGroup);
    if ((type < 0) || (type >= Nmodels)) {
        psError(PS_ERR_UNKNOWN, true, "Undefined pmModelType");
        return (0);
    }
    return (models[type].nParams);
}

psS32 pmModelSetType (char *name)
{

    int Nmodels = sizeof (models) / sizeof (pmModelGroup);
    for (int i = 0; i < Nmodels; i++) {
        if (!strcmp(models[i].name, name)) {
            return (i);
        }
    }
    return (-1);
}

char *pmModelGetType (pmModelType type)
{

    int Nmodels = sizeof (models) / sizeof (pmModelGroup);
    if ((type < 0) || (type >= Nmodels)) {
        psError(PS_ERR_UNKNOWN, true, "Undefined pmModelType");
        return (NULL);
    }
    return (models[type].name);
}
