/**
 * @file JAModeControlGAM.cpp
 * @brief Source file for class JAModeControlGAM
 * @date Jan, 2019
 * @author kuchida
 *
 * @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and
 * the Development of Fusion Energy ('Fusion for Energy').
 * Licensed under the EUPL, Version 1.1 or - as soon they will be approved
 * by the European Commission - subsequent versions of the EUPL (the "Licence")
 * You may not use this work except in compliance with the Licence.
 * You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
 *
 * @warning Unless required by applicable law or agreed to in writing,
 * software distributed under the Licence is distributed on an "AS IS"
 * basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the Licence permissions and limitations under the Licence.

 * @details This source file contains the definition of all the methods for
 * the class JAModeControlGAM (public, protected, and private). Be aware that some
 * methods, such as those inline could be defined on the header file, instead.
 */

/*---------------------------------------------------------------------------*/
/*                         Standard header includes                          */
/*---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
/*                         Project header includes                           */
/*---------------------------------------------------------------------------*/
#include "JAModeControlGAM.h"
#include "AdvancedErrorManagement.h"

/*---------------------------------------------------------------------------*/
/*                           Static definitions                              */
/*---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
/*                           Method definitions                              */
/*---------------------------------------------------------------------------*/

JAModeControlGAM::JAModeControlGAM() {
    inputSignals = NULL_PTR(MARTe::uint32 **);
    outputSignal = NULL_PTR(MARTe::uint32 *);
    pulseLengthLimit = 360000000u;
    resetRemainingTime = true;
    previousState = 0u;
}

JAModeControlGAM::~JAModeControlGAM() {
    if (inputSignals != NULL_PTR(MARTe::uint32 **)) {
        delete[] inputSignals;
    }
}

bool JAModeControlGAM::Initialise(MARTe::StructuredDataI & data) {
    /* read hard coded on cfg file parameter values by using key name. */
    using namespace MARTe;
    return GAM::Initialise(data);
}

bool JAModeControlGAM::Setup() {
    /* read GAM Input signal */
    using namespace MARTe;
    /* read 4 mode bits and 4 shot length limit values */

    bool ok = numberOfInputSignals == 11;
    if (ok) {
        uint32 i;
        for (i = 0u; (i < numberOfInputSignals) && (ok); i++) {
            TypeDescriptor inputType = GetSignalType(InputSignals, i);
            ok = inputType == UnsignedInteger32Bit;
            if (!ok) {
                StreamString signalName;
                (void) GetSignalName(InputSignals, i, signalName);
                REPORT_ERROR(ErrorManagement::ParametersError, "InputSignel %s shall be defined as uint32", signalName.Buffer());
            }
        }
    }
    else {
        REPORT_ERROR(ErrorManagement::ParametersError, "Eleven input signals shall be defined.");
    }
    if (ok) {
        ok = numberOfOutputSignals == 1;
        if (!ok) {
            REPORT_ERROR(ErrorManagement::ParametersError, "One output signal shall be defined.");
        }
        else {
            TypeDescriptor type = GetSignalType(OutputSignals, 0);
            ok = type == UnsignedInteger32Bit;
            if (!ok) {
                StreamString signalName;
                (void) GetSignalName(OutputSignals, 0, signalName);
                REPORT_ERROR(ErrorManagement::ParametersError, "Signal %s shall be defined as uint32", signalName.Buffer());
            }
        }
    }
    if (ok) {
        outputSignal = reinterpret_cast<uint32 *>(GetOutputSignalMemory(0));
        inputSignals = new uint32*[numberOfInputSignals];
        uint32 i;
        for (i = 0u; i < 11; i++) {
            inputSignals[i] = reinterpret_cast<uint32 *>(GetInputSignalMemory(i));
        }
    }
    return ok;
}

bool JAModeControlGAM::PrepareNextState(const MARTe::char8 * const currentStateName, const MARTe::char8 * const nextStateName) {
    *outputSignal = 0u;
    previousState = 0u;
    resetRemainingTime = true;
    return true;
}

bool JAModeControlGAM::Execute() {
    using namespace MARTe;
    //When RT state goes to RFON state, update the limit.
    if(previousState == 0u && *inputSignals[8] == 1u && resetRemainingTime) {
        rfonTime = *inputSignals[9];
        resetRemainingTime = false;
        pulseLengthLimit = CalcPulseLengthLimit(inputSignals);
        REPORT_ERROR(ErrorManagement::Debug, "Pulse Length was set to Limit:%d", pulseLengthLimit);
    } 
    // Turn on the flag during RFON if the pulse legth over the limit.
    if ((*inputSignals[9] - rfonTime <= pulseLengthLimit) && (previousState == 1u)) {
        *outputSignal = 0u;
        return true;
    }  else if(*inputSignals[9] == 1u){
        resetRemainingTime = true;
        *outputSignal = 1u;
    }

    previousState = *inputSignals[8];
    return true;
}


MARTe::uint32 JAModeControlGAM::CalcPulseLengthLimit(MARTe::uint32 **inputSignals) {
    if (*inputSignals[0] == 1) {
        return *inputSignals[1];
    } else if (*inputSignals[2] == 1) {
        return *inputSignals[3];
    } else if (*inputSignals[4] == 1) {
        return *inputSignals[5];
    } else if (*inputSignals[6] == 1) {
        return *inputSignals[7];
    } else {
        return 3600000000;//us
    }
}


CLASS_REGISTER(JAModeControlGAM, "1.0")
