/*
 * guidetool.c
 *
 * Copyright (C) 2006  Joshua Hoblitt
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; version 2 of the License.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * program; see the file COPYING. If not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdlib.h>

#include "pxtools.h"
#include "guidetool.h"

static bool pendingMode(pxConfig *config);
static bool defineMode(pxConfig *config);
static guidePendingExpRow *rawScienceToguidePendingExp(pxConfig *config, rawScienceExpRow *exp);

int main(int argc, char **argv)
{
    pxConfig *config = guidetoolConfig(NULL, argc, argv);

    switch (config->mode) {
        case PX_MODE_PENDING:
            if (!pendingMode(config)) {
                goto FAIL;
            }
            break;
        case PX_MODE_DEFINE:
            if (!defineMode(config)) {
                goto FAIL;
            }
            break;
        default:
            psAbort("invalid option (this should not happen)");
    }

    exit(EXIT_SUCCESS);

FAIL:
    psFree(config);
    exit(EXIT_FAILURE);
}

static bool pendingMode(pxConfig *config)
{
    PS_ASSERT_PTR_NON_NULL(config, false);

    psMetadata *where = psMetadataAlloc();
    PXOPT_COPY_STR(config->args, where, "-exp_id",        "exp_id", "==");
    PXOPT_COPY_STR(config->args, where, "-inst",          "camera", "==");
    PXOPT_COPY_STR(config->args, where, "-telescope", 	  "telescope", "==");
    PXOPT_COPY_STR(config->args, where, "-exp_type",  	  "exp_type", "==");
    PXOPT_COPY_S32(config->args, where, "-imfiles",   	  "imfiles", "==");
    PXOPT_COPY_STR(config->args, where, "-filter",    	  "filter", "==");
    PXOPT_COPY_STR(config->args, where, "-recip",         "recipe", "==");
    PXOPT_COPY_S32(config->args, where, "-guide_version", "guide_version", "==");
    if (!psListLength(where->list)) {
	psFree (where);
	where = NULL;
    }

    // return all guidePendingExp rows unless there CLI search options
    psArray *guidePendingExp = guidePendingExpSelectRowObjects(config->dbh, where, 0);
    psFree (where);

    if (!guidePendingExp) {
        psError(PS_ERR_UNKNOWN, false, "no guidePendingExp found");
        return false;
    }
    psMetadata *output = psMetadataAlloc();

    for (long i = 0; i < psArrayLength(guidePendingExp); i++) {
        psMetadata *md = guidePendingExpMetadataFromObject(guidePendingExp->data[i]);
        psMetadataAddMetadata(output, PS_LIST_TAIL, "guidePendingExp",
            PS_META_DUPLICATE_OK, NULL, md);
        psFree(md);
    }

    psString str = psMetadataConfigFormat(output);
    psFree(output);

    fprintf(stdout, "%s\n", str);
    psFree(str);

    return true;
}

static bool defineMode(pxConfig *config)
{
    PS_ASSERT_PTR_NON_NULL(config, false);
    
    psMetadata *where = psMetadataAlloc();
    PXOPT_COPY_STR(config->args, where, "-exp_id",        "exp_id", "==");
    PXOPT_COPY_STR(config->args, where, "-inst",          "camera", "==");
    PXOPT_COPY_STR(config->args, where, "-telescope", 	  "telescope", "==");
    PXOPT_COPY_STR(config->args, where, "-exp_type",  	  "exp_type", "==");
    PXOPT_COPY_S32(config->args, where, "-imfiles",   	  "imfiles", "==");
    PXOPT_COPY_STR(config->args, where, "-filter",    	  "filter", "==");
    if (!psListLength(where->list)) {
	psFree (where);
	where = NULL;
    }

    // return all rawScienceExp rows unless there CLI search options
    psArray *rawScienceExps = rawScienceExpSelectRowObjects(config->dbh, where, 0);
    psFree (where);
    
    if (!rawScienceExps) {
        psError(PS_ERR_UNKNOWN, false, "no rawScienceExp rows found");
        return true;
    }

    // insert the rawScienceExps into guidePendingExp
    // XXX for the being we're going to skip checking for duplicate entries
    // XXX this will have to implimented unless duplicate key insertion 
    // XXX support is implimented in psDB
    for (long i = 0; i < psArrayLength(rawScienceExps); i++) {
        guidePendingExpRow * new = rawScienceToguidePendingExp(
                                            config, rawScienceExps->data[i]);
        if (!guidePendingExpInsertObject(config->dbh, new)) {
            psError(PS_ERR_UNKNOWN, false, "dbh access failed");
            return false; 
        }
        psFree(new);
    }

    return true;
}

static guidePendingExpRow *rawScienceToguidePendingExp(pxConfig *config, rawScienceExpRow *exp)
{
    PS_ASSERT_PTR_NON_NULL(config, NULL);
    PS_ASSERT_PTR_NON_NULL(exp, NULL);

    bool status = false;
    psString filter = psMetadataLookupStr(&status, config->args, "-filter");
    if (!status) {
        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -filter");
        return false;
    }
    if (!filter) {
        psError(PS_ERR_UNKNOWN, true, "-filter is required");
        return false;
    }
    psF32 airmass = psMetadataLookupF32(&status, config->args, "-airmass");
    if (!status) {
        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -airmass");
        return false;
    }
    if (!airmass) {
        psError(PS_ERR_UNKNOWN, true, "-airmass is required");
        return false;
    }
    psF64 ra = psMetadataLookupF64(&status, config->args, "-ra");
    if (!status) {
        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -ra");
        return false;
    }
    if (!ra) {
        psError(PS_ERR_UNKNOWN, true, "-airmass is required");
        return false;
    }
    psF64 dec = psMetadataLookupF64(&status, config->args, "-dec");
    if (!status) {
        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -dec");
        return false;
    }
    if (!dec) {
        psError(PS_ERR_UNKNOWN, true, "-dec is required");
        return false;
    }
    psF32 exp_time = psMetadataLookupF32(&status, config->args, "-exp_time");
    if (!status) {
        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -exp_time");
        return false;
    }
    if (!exp_time) {
        psError(PS_ERR_UNKNOWN, true, "-exp_time is required");
        return false;
    }
    psF64 background = psMetadataLookupF64(&status, config->args, "-background");
    if (!status) {
        psError(PS_ERR_UNKNOWN, false, "failed to lookup value for -background");
        return false;
    }
    if (!exp_time) {
        psError(PS_ERR_UNKNOWN, true, "-background is required");
        return false;
    }

    return guidePendingExpRowAlloc(
        exp->exp_id,
        exp->camera,
        exp->telescope,
        exp->exp_type,
        exp->imfiles,
        filter,
        airmass,
        ra,
        dec,
        exp_time,
        background,
        "my recipe",
        0xff // XXX calc version number
    );
}
