// $Id: Arams.cpp,v 1.5 2003/03/19 16:49:24 fukasawa Exp $

//=============================================================================
/**
 *  @file    Arams.cpp
 *
 *  @author Fukasawa Mitsuo
 *
 *
 *    Copyright (C) 1998-2003 BEE Co.,Ltd. All rights reserved.
 *
 * 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; either version 2
 * of the License, or (at your option) any later version.
 *
 * 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 this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
//=============================================================================

#define BEE_BUILD_DLL

#include "arams/Arams.h"
#include "JGEquipment.h"
#include "JGInfoManager.h"
#include "JGTaskTrigger.h"
#include "BS2ACKMessage.h"
#include "BS2ErrorMessage.h"
#include "BS2ListItem.h"
#include "BS2DeclAtoms.h"

//-----------------------------------------------------------------------------
//
// ARAMS Object
//
//-----------------------------------------------------------------------------
MANAGER_STATE(AramsState, Arams, CATEGORY_ARAMS);

    CONDITION_STATE(CondArams);
    CONDITION_STATE(CondManufacturing);
    EDGE_STATE(Productive);
    EDGE_STATE(Standby);
    EDGE_STATE(Engineering);
    EDGE_STATE(UnscheduledDowntime);
    EDGE_STATE(ScheduledDowntime);
    EDGE_STATE(NonScheduledDowntime);

    // Define transit and state functions
    const BCHAR * toSelect(JGTrigger * trigger);
    const BCHAR * toPowerOFF(JGTrigger * trigger);

END_ROOT_STATE();

//------------------------------------------------------------------------------
// State
//------------------------------------------------------------------------------
#define STATE_TOTAL_TIME            _TX("/TOTAL")
#define STATE_UPTIME                _TX("/TOTAL/UPTIME")
#define STATE_MANUFACTURING         _TX("/TOTAL/UPTIME/MANUFACTURING")
#define STATE_PRODUCTIVE            _TX("/TOTAL/UPTIME/MANUFACTURING/PRODUCTIVE")
#define STATE_STANDBY               _TX("/TOTAL/UPTIME/MANUFACTURING/STANDBY")
#define STATE_ENGINEERING           _TX("/TOTAL/UPTIME/ENGINEERING")
#define STATE_UNSCHEDULED_DOWNTIME  _TX("/TOTAL/UNSCHEDULED_DOWNTIME")
#define STATE_SCHEDULED_DOWNTIME    _TX("/TOTAL/SCHEDULED_DOWNTIME")
#define STATE_NON_SCHEDULED_TIME    _TX("/TOTAL/NON-SCHEDULED_TIME")

//------------------------------------------------------------------------------
static AramsState::CondArams            _st_total(STATE_TOTAL_TIME);
static AramsState::CondManufacturing    _st_manufact(STATE_MANUFACTURING);
static HistState                        _st_uptime(STATE_UPTIME, STATE_MANUFACTURING);
static AramsState::Productive           _st_productive(STATE_PRODUCTIVE);
static AramsState::Standby              _st_standby(STATE_STANDBY);
static AramsState::Engineering          _st_engineering(STATE_ENGINEERING);
static AramsState::UnscheduledDowntime  _st_unscheduled_downtime(STATE_UNSCHEDULED_DOWNTIME);
static AramsState::ScheduledDowntime    _st_scheduled_downtime(STATE_SCHEDULED_DOWNTIME);
static AramsState::NonScheduledDowntime _st_non_scheduled_time(STATE_NON_SCHEDULED_TIME);

//-----------------------------------------------------------------------------
//
// Transition of Arams Manager
//
//-----------------------------------------------------------------------------
DEF_ACTION(AramsState, toSelect);
DEF_ACTION(AramsState, toPowerOFF);

//------------------------------------------------------------------------------
BEGIN_STATIC_STATE_TABLE(AramsState);
    NEXT_TRANSITION(&JGStateTask::Root, TRIGGER_START, STATE_TOTAL_TIME, _TX("NULL"));
    NODE_TRANSITION(&_st_total, _TX("TOTAL TIME"));
    NODE_TRANSITION(&_st_uptime, _TX("UPTIME"));
    NODE_TRANSITION(&_st_manufact, _TX("MANUFACTURING TIME"));
    NEXT_TRANSITION(&_st_standby,
                    TRIGGER_PRODUCTIVE,
                    STATE_PRODUCTIVE,
                    _TX("STANDBY --> PRODUCTIVE"));
    NEXT_TRANSITION(&_st_productive,
                    TRIGGER_STANDBY,
                    STATE_STANDBY,
                    _TX("PRODUCTIVE --> STANDBY"));
    NEXT_TRANSITION(&_st_productive,
                    TRIGGER_EXCEPTION,
                    STATE_UNSCHEDULED_DOWNTIME,
                    _TX("PRODUCTIVE --> UNSCHEDULED DOWNTIME"));
    NEXT_TRANSITION(&_st_unscheduled_downtime, // transit 6,8 or 15
                    TRIGGER_CLEAR_FAULT,
                    STATE_UPTIME,
                    _TX("UNSCHEDULED DOWNTIME --> UPTIME"));
    NEXT_TRANSITION(&_st_standby,
                    TRIGGER_DETECT_FAULT,
                    STATE_UNSCHEDULED_DOWNTIME,
                    _TX("UPTIME --> UNSCHEDULED DOWNTIME"));
    NEXT_TRANSITION(&_st_standby,
                    TRIGGER_LIMIT,
                    STATE_SCHEDULED_DOWNTIME,
                    _TX("STANDBY --> SCHEDULED DOWNTIME"));
    ACT_TRANSITION( &_st_standby,
                    TRIGGER_USER_SELECT,
                    toSelect,
                    _TX("STANDBY --> user selects code"));
    ACT_TRANSITION( &_st_productive,
                    TRIGGER_USER_SELECT,
                    toSelect,
                    _TX("PRODUCTIVE --> user selects code"));
    ACT_TRANSITION( &_st_engineering,
                    TRIGGER_USER_SELECT,
                    toSelect,
                    _TX("ENGINEERING --> user selects code"));
    ACT_TRANSITION( &_st_unscheduled_downtime,
                    TRIGGER_USER_SELECT,
                    toSelect,
                    _TX("UNSCHEDULED DOWNTIME --> user selects code"));
    ACT_TRANSITION( &_st_scheduled_downtime,
                    TRIGGER_USER_SELECT,
                    toSelect,
                    "SCHEDULED DOWNTIME --> user selects code");
    ACT_TRANSITION( &_st_non_scheduled_time,
                    TRIGGER_USER_SELECT,
                    toSelect,
                    _TX("NON-SCHEDULED TIME --> user selects code"));
    ACT_TRANSITION( &_st_standby,
                    TRIGGER_USER_SELECT,
                    toPowerOFF,
                    _TX("STANDBY --> user selects code"));
    ACT_TRANSITION( &_st_productive,
                    TRIGGER_POWER_OFF,
                    toPowerOFF,
                    "PRODUCTIVE --> user selects code");
    ACT_TRANSITION( &_st_engineering,
                    TRIGGER_POWER_OFF,
                    toPowerOFF,
                    _TX("ENGINEERING --> user selects code"));
    ACT_TRANSITION( &_st_unscheduled_downtime,
                    TRIGGER_POWER_OFF,
                    toPowerOFF,
                    _TX("UNSCHEDULED DOWNTIME --> user selects code"));
    ACT_TRANSITION( &_st_scheduled_downtime,
                    TRIGGER_POWER_OFF,
                    toPowerOFF,
                    _TX("SCHEDULED DOWNTIME --> user selects code"));
    ACT_TRANSITION( &_st_non_scheduled_time,
                    TRIGGER_POWER_OFF,
                    toPowerOFF,
                    "NON-SCHEDULED TIME --> user selects code");
    NEXT_TRANSITION( &_st_standby,
                     TRIGGER_STANDBY,
                     STATE_STANDBY,
                     _TX("STANDBY --> STANDBY"));
    NEXT_TRANSITION( &_st_productive,
                     TRIGGER_PRODUCTIVE,
                     STATE_PRODUCTIVE,
                     _TX("PRODUCTIVE --> PRODUCTIVE"));
    NEXT_TRANSITION( &_st_engineering,
                     TRIGGER_DETECT_FAULT,
                     STATE_UNSCHEDULED_DOWNTIME,
                     _TX("ENGINEERING --> PRODUCTIVE"));
END_STATE_TABLE();

//-----------------------------------------------------------------------------
//
// State procedures
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Action: Productive
//-----------------------------------------------------------------------------
int AramsState::actProductive(JGState * prev, JGTrigger * trigger)
{
    TRACE_FUNCTION(TRL_LOW, "AramsState::actProductive");
    ACE_UNUSED_ARG(prev);
    ACE_UNUSED_ARG(trigger);
    return BEE_SUCCESS;
}

//-----------------------------------------------------------------------------
// Action: Standby
//-----------------------------------------------------------------------------
int AramsState::actStandby(JGState * prev, JGTrigger * trigger)
{
    TRACE_FUNCTION(TRL_LOW, "AramsState::actStandby");
    ACE_UNUSED_ARG(prev);
    ACE_UNUSED_ARG(trigger);
    return BEE_SUCCESS;
}

//-----------------------------------------------------------------------------
// Action: Engineering
//-----------------------------------------------------------------------------
int AramsState::actEngineering(JGState * prev, JGTrigger * trigger)
{
    TRACE_FUNCTION(TRL_LOW, "AramsState::actEngineering");
    ACE_UNUSED_ARG(prev);
    ACE_UNUSED_ARG(trigger);
    return BEE_SUCCESS;
}

//-----------------------------------------------------------------------------
// Action: Unscheduled downtime
//-----------------------------------------------------------------------------
int AramsState::actUnscheduledDowntime(JGState * prev, JGTrigger * trigger)
{
    TRACE_FUNCTION(TRL_LOW, "AramsState::actUnscheduledDowntime");
    ACE_UNUSED_ARG(trigger);

    int result = BEE_SUCCESS;
    if (prev->name() == STATE_PRODUCTIVE)
    {
        m_manager->m_InterruptionPrd++;
        JGvalue count = m_manager->m_InterruptionPrd;
        m_manager->m_InterruptionCtr->setv(count);
    }
    m_manager->m_InterruptionTotal++;
    return result;
}

//-----------------------------------------------------------------------------
// Action: Scheduled downtime
//-----------------------------------------------------------------------------
int AramsState::actScheduledDowntime(JGState * prev, JGTrigger * trigger)
{
    TRACE_FUNCTION(TRL_LOW, "AramsState::actScheduledDowntime");
    ACE_UNUSED_ARG(prev);
    ACE_UNUSED_ARG(trigger);
    return BEE_SUCCESS;
}

//-----------------------------------------------------------------------------
// Action: Non-scheduled downtime
//-----------------------------------------------------------------------------
int AramsState::actNonScheduledDowntime(JGState * prev, JGTrigger * trigger)
{
    TRACE_FUNCTION(TRL_LOW, "AramsState::actNonScheduledDowntime");
    ACE_UNUSED_ARG(prev);
    ACE_UNUSED_ARG(trigger);
    return BEE_SUCCESS;
}

//-----------------------------------------------------------------------------
// Transition: User selects sub-state code
//-----------------------------------------------------------------------------
const BCHAR * AramsState::toSelect(JGTrigger * trigger)
{
    TRACE_FUNCTION(TRL_LOW, "AramsState::toSelect");
    const BCHAR * nextState = ((JGOperatorTrigger *)trigger)->name().c_str();

    return nextState;
}

//-----------------------------------------------------------------------------
// Transition: Power OFF: save sub-state when the power is turned on
//-----------------------------------------------------------------------------
const BCHAR * AramsState::toPowerOFF(JGTrigger * trigger)
{
    TRACE_FUNCTION(TRL_LOW, "AramsState::toPowerOFF");
    ACE_UNUSED_ARG(trigger);

    const BCHAR * nextState = JGStateTask::Root.name().c_str();

    // save current ?

    return nextState;
}

//------------------------------------------------------------------------------
// Condition node actions
//------------------------------------------------------------------------------
const BCHAR * AramsState::actCondArams(JGTrigger * trigger)
{
    TRACE_FUNCTION(TRL_LOW, "AramsState::actCondArams");
    ACE_UNUSED_ARG(trigger);

    BCHAR * nextName;
    // Power ON
    nextName = STATE_MANUFACTURING;
    return nextName;
}

//------------------------------------------------------------------------------
const BCHAR * AramsState::actCondManufacturing(JGTrigger * trigger)
{
    TRACE_FUNCTION(TRL_LOW, "AramsState::actCondManufacturing");
    ACE_UNUSED_ARG(trigger);

    BCHAR * nextName;
    // Standby or Product
    nextName = STATE_STANDBY;
    return nextName;
}

//-----------------------------------------------------------------------------
// Unexpected event
//-----------------------------------------------------------------------------
int AramsState::unexpect(b_trigger * trigger)
{
    TRACE_FUNCTION(TRL_LOW, "AramsState::unexpect");

    //if (trigger->name() == TRIGGER_S2F41)
    //{
    //}
    //else
    {
        this->b_context::unexpect(trigger);
    }

    return BEE_ERROR;
}

//
//
// A R A M S
//
//
//-----------------------------------------------------------------------------
// Return own.
//-----------------------------------------------------------------------------
static Arams * _manager = NULL;

Arams * Arams::instance()
{
    TRACE_FUNCTION(TRL_LOW, "Arams::instance");
    if (_manager == NULL)
    {
        _manager = new Arams;
    }
    return _manager;
}

//-----------------------------------------------------------------------------
// Constructor/Destoructor
//-----------------------------------------------------------------------------
Arams::Arams() : JGManager(CATEGORY_COMM)
{
    TRACE_FUNCTION(TRL_LOW, "Arams::Arams");
}

//-----------------------------------------------------------------------------
// Initialize
//-----------------------------------------------------------------------------
int Arams::init(void * parm)
{
    TRACE_FUNCTION(TRL_LOW, "Arams::init");
    ACE_UNUSED_ARG(parm);

    // Get Variables of Communications
    m_ARAMSAccumReset = m_equipment->variable(_TX("ARAMSAccumReset"));
    m_ARAMSInfo = m_equipment->variable(_TX("ARAMSInfo"));
    m_ARAMSState = m_equipment->variable(_TX("ARAMSState"));
    m_ARAMSText = m_equipment->variable(_TX("ARAMSText"));
    m_ARAMSTimestamp = m_equipment->variable(_TX("ARAMSTimeStamp"));
    m_DowntimeAlarm = m_equipment->variable(_TX("DowntimeAlarm"));
    m_DowntimeAlarmText = m_equipment->variable(_TX("DowntimeAlarmText"));
    m_DowntimeData = m_equipment->variable(_TX("DowntimeData"));
    m_EngTime = m_equipment->variable(_TX("EngTime"));
    m_InterruptionCtr = m_equipment->variable(_TX("InterruptionCtr"));
    m_LastPowerdown = m_equipment->variable(_TX("LastPowerdown"));
    m_NSTime = m_equipment->variable(_TX("NSTime"));
    m_PowerdownTime = m_equipment->variable(_TX("PowerdoownTime"));
    m_PowerupState = m_equipment->variable(_TX("PowerupState"));
    m_PrdRecovery = m_equipment->variable(_TX("PrdRecovery"));
    m_PrdState = m_equipment->variable(_TX("PrdState"));
    m_PrdTime = m_equipment->variable(_TX("PrdTime"));
    m_PrevARAMSState = m_equipment->variable(_TX("PrevARAMSState"));
    m_SbyRecovery = m_equipment->variable(_TX("SbyRecovery"));
    m_SbyTime = m_equipment->variable(_TX("SbyTime"));
    m_SDTime = m_equipment->variable(_TX("SDTime"));
    m_SymptomID = m_equipment->variable(_TX("SymptomID"));
    m_SymptomText = m_equipment->variable(_TX("SymptomText"));
    m_UDTime = m_equipment->variable(_TX("UDTime"));

    // Initial State Model
    m_aramsState = _AramsState::instance();
    m_aramsState->manager(this);
    m_aramsState->equipment(m_equipment);
    m_aramsState->init();         // initialized transitions
    // m_aramsState->open();      // start thread

    return BEE_SUCCESS;
}

//-----------------------------------------------------------------------------
// Update status
//-----------------------------------------------------------------------------
int Arams::update(JGState * state)
{
    TRACE_FUNCTION(TRL_LOW, "Arams::update");
    int result = BEE_SUCCESS;

    m_PrevARAMSState->setv(m_ARAMSState->getv());
    JGvalue state_val = state->name();
    m_ARAMSState->setv(state_val);

    return result;
}

//--------------------------------------------------------------------------
// Get system time
//-----------------------------------------------------------------------------
void Arams::getClock(string& tmbuf)
{
    TRACE_FUNCTION(TRL_LOW, "Arams::getClock");
    ACE_UNUSED_ARG(tmbuf);
    //m_equipment->getClock(tmbuf);
    return ;
}

//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
UINT Arams::getCycleCtr()
{
    TRACE_FUNCTION(TRL_LOW, "Arams::getCycleCtr");
    //m_equipment->getCycleCtr();
    return 0;
}


//-----------------------------------------------------------------------------
// Get Equipment model name
//-----------------------------------------------------------------------------
const string& Arams::getEqpModel() const
{
    TRACE_FUNCTION(TRL_LOW, "Arams::getEqpModel");
    //m_equipment->getModelNumber();
    return m_mdln;
}

//-----------------------------------------------------------------------------
// Get Equipment serial number
//-----------------------------------------------------------------------------
const string& Arams::getSerialNum() const
{
    TRACE_FUNCTION(TRL_LOW, "Arams::getSerialNum");
    // m_equipment->getSerialNumber();
    return m_serial;
}

//-----------------------------------------------------------------------------
//
// Service of received message.
//
//-----------------------------------------------------------------------------
BS2Message * Arams::msg_svc(JGTrigger * trigger, BS2Message * msg)
{
    BS2Message * replymsg = NULL;
    ACE_UNUSED_ARG(trigger);

    //if (msg->sf() == SFCODE(2,41))
    {   // Unexpected message
        replymsg = this->unrecognized(msg);
    }

    return replymsg;
}

//-----------------------------------------------------------------------------
// Dump
//-----------------------------------------------------------------------------
void Arams::dump() const
{
}

