#include "filesys.h"
#include "validate_util.h"
#include "ap_result.h"

std::string ResultFile::get_result_file(RESULT& r)
{
        int retval;
        std::string path_str;
        const char *path;

#ifdef TEST
	SCHED_CONFIG config;
	retval = config.parse_file("../");
	if (retval) {
		std::cout << "Could not parse config.xml!!" << std::endl;
		throw ResultFileError("Could not parse data from config.xml.");
	}
	//std::cout << "Parse data from config file." << std::endl;
#else
    extern SCHED_CONFIG config;
#endif

    retval = get_output_file_path(r, path_str);
    if (retval) {
        if (retval == ERR_XML_PARSE) {
                log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,
                        "[%s] Cannot extract filename from canonical result %ld.\n",
                        r.name,  r.id);
		throw ResultFileError("Cannot extract filename from canonical result.");
        } else {
                log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,
                        "[%s] unknown error from get_output_file_path() for result %ld.\n",
                        r.name,  r.id);
		throw ResultFileError("unknown error from get_output_file_path");
        }
     } else {
        path = (char *)path_str.c_str();
        if (!boinc_file_exists(path)) {
                log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,
                        "[%s] Output file %s does not exist for result %ld\n",
                        r.name, path,  r.id);
		throw ResultFileError("Output file does not exist for result");
        }
    }

        

        return path_str;

}

int ResultFile::parse_file(RESULT& result)
{
	std::string str = "";
	char buff[1024];
	try {
	  str=get_result_file(result);
	} catch (ResultFileError &rerr) {
          throw;
	}


        std::ifstream fd(str.c_str());

	/*get the file descriptor and open result file*/

        if (!fd) 
	   throw ResultFileError("Could not open result file.");

	//if str is empty throw ResultFileError
	//std::cout << str.length() << std::endl;

	/*------parse variable value----*/
	long first = 0, second = 0;
	std::string str_tmp;  //temporary string for parsing detail.
	bool retval = true;
	int i;
	double d;

        fd.clear();
        fd.seekg(0);

        workunit_header wu;
        fd >> wu;

	//Decode Threshold Values
        thresholds.resize(wu.analysis_cfg->max_coadd);
        std::vector<threshold_t>::iterator t=wu.analysis_cfg->thresholds.begin();
        for (  ; t!=wu.analysis_cfg->thresholds.end() ; t++ )
           thresholds[t->coadds]=t->threshold;

        fd.clear();
        fd.seekg(0);

        while (!fd.eof()) {
            ap_signal ps; 
            fd >> ps;

            // ignore signals below threshold or with invalid scale factors. 
            if ((thresholds.size() == 0) || ((static_cast<size_t>(ps.scale)<thresholds.size()) && (ps.peak_power > (thresholds[ps.scale] * THRESHOLD_FUDGE))))
			pulses.push_back(ps);
	}

	has_pulse = true;
	return 0;
}

int ResultFile::overflow_result(RESULT& result)
{
	char buf[1024];

	if (parse_str(result.stderr_out, "<stderr_txt>", buf, sizeof(buf))) {
		if (strstr(buf, "result_overflow")) {
			return -1;
		} else {
			return 0;
		}
	} else {
		log_messages.printf(SCHED_MSG_LOG::MSG_DEBUG,
						"[RESULT#%d] parse_str does not find stderr_txt",
						result.id);
	}
	return 0;
}

int ResultFile::init(RESULT& result)
{
	result_id = result.id;
	claimed_credit = result.claimed_credit;
	has_pulse = false;

	if (!overflow_result(result)) {
		try {
			parse_file(result);
		} catch (ResultFileError &rerr) {
			log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL, "[RESULT#%d] %s\n",
							result.id, rerr.what().c_str());

			result.outcome = RESULT_OUTCOME_VALIDATE_ERROR;
			result.validate_state = VALIDATE_STATE_INVALID;
			return -1;
		}
	} else {
		log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,
						"[RESULT#%d] Result was overflow\n", result.id);
		return -1;
	}
	return 0;
}

ResultFile::ResultFile(RESULT& result)
	: track_mem<ResultFile>("ResultFile"), has_pulse(false)
{
	try {
		if (init(result) == -1) {
			log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL,
							"[RESULT#%d] Couldn't create AP_RESULT object.\n",
							result.id);
			throw ResultFileError("Couldn't create AP_RESULT object.");
		}
	} catch (ResultFileError &rerr) {
		log_messages.printf(SCHED_MSG_LOG::MSG_CRITICAL, "[RESULT#%d] %s\n",
						result.id, rerr.what().c_str());
		throw;  //re-throw the exception.
	}
}


