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

#include <stdio.h>
#include <pslib.h>

#include "pmSubtractionMatch.h"
#include "pmSubtractionEquation.h"
#include "pmSubtraction.h"

bool threaded = false;                  // Run with threads?

bool pmSubtractionThreaded(void)
{
    return threaded;
}

// Initialise a mutex in each of the input
static void subtractionMutexInit(pmReadout *ro)
{
    if (!ro) {
        return;
    }

    if (ro->image) {
        psMutexInit(ro->image);
    }
    if (ro->weight) {
        psMutexInit(ro->weight);
    }

    return;
}

static void subtractionMutexDestroy(pmReadout *ro)
{
    if (!ro) {
        return;
    }

    if (ro->image) {
        psMutexDestroy(ro->image);
    }
    if (ro->weight) {
        psMutexDestroy(ro->weight);
    }

    return;
}

void pmSubtractionThreadsInit(pmReadout *in1, pmReadout *in2)
{
    if (threaded) {
        psAbort("Already running threaded.");
    }

    threaded = true;

    subtractionMutexInit(in1);
    subtractionMutexInit(in2);

    {
        psThreadTask *task = psThreadTaskAlloc("PSMODULES_SUBTRACTION_ORDER", 8);
        task->function = &pmSubtractionOrderThread;
        psThreadTaskAdd(task);
        psFree(task);
    }

    {
        psThreadTask *task = psThreadTaskAlloc("PSMODULES_SUBTRACTION_CALCULATE_EQUATION", 3);
        task->function = &pmSubtractionCalculateEquationThread;
        psThreadTaskAdd(task);
        psFree(task);
    }

    {
        psThreadTask *task = psThreadTaskAlloc("PSMODULES_SUBTRACTION_CONVOLVE", 19);
        task->function = &pmSubtractionConvolveThread;
        psThreadTaskAdd(task);
        psFree(task);
    }

    return;
}


void pmSubtractionThreadsFinalize(pmReadout *in1, pmReadout *in2)
{
    if (!threaded) {
        return;
    }

    threaded = false;
    psThreadTaskRemove("PSMODULES_SUBTRACTION_ORDER");
    psThreadTaskRemove("PSMODULES_SUBTRACTION_CALCULATE_EQUATION");
    psThreadTaskRemove("PSMODULES_SUBTRACTION_CONVOLVE");

    subtractionMutexDestroy(in1);
    subtractionMutexDestroy(in1);
    return;
}
