// $Id: JGPLCManager.cpp,v 1.3 2003/02/02 15:56:01 fukasawa Exp $

//=============================================================================
/**
 *  @file    JGPLCManager.cpp
 *
 *  @author  Fukasawa Mitsuo
 *
 *
 *    Copyright (C) 2001-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 "JGEquipmentModule.h"
#include "JGPLCManager.h"
#include "SACXmlParser.h"
#include "PLCDeviceManager.h"

typedef PLCDeviceManager * (*PLCManagerCreator)(void);

//-----------------------------------------------------------------------------
// Constructor/Destructor
//-----------------------------------------------------------------------------
JGPLCManager::~JGPLCManager()
{
    TRACE_FUNCTION(TRL_CONSTRUCT, "JGPLCManager::~JGPLCManager");

    JGPLCDeviceTable::iterator iter = m_devs.begin();
    for ( ; iter != m_devs.end(); iter++)
    {
        JGPLCDevice * plc = (*iter).second;
        delete plc;
    }
}

//-----------------------------------------------------------------------------
// Load & link PLC driver
//-----------------------------------------------------------------------------
int JGPLCManager::linkPLCDriver()
{
    TRACE_FUNCTION(TRL_LOW, "JGPLCManager::linkPLCDriver");

    int result;
    result = m_dll.open(m_dllname.c_str());   // Load PLC Manager's DLL
    if (result != 0)
    {
        TRACE_ERROR((_TX("%p"), _TX("dll.open")));
        return -1;
    }
    PLCManagerCreator pmc;
    pmc = (PLCManagerCreator)m_dll.symbol("CreatePLC");
    if (pmc == 0)
    {
        TRACE_ERROR((_TX("%p"), _TX("dll.symbol")));
        return -1;
    }
    m_plcmngr = pmc();
    return 0;
}

//-----------------------------------------------------------------------------
// Initialize
//-----------------------------------------------------------------------------
int JGPLCManager::init(JGEquipmentModule& equipment)
{
    TRACE_FUNCTION(TRL_LOW, "JGPLCManager::init");

    int result;
    m_dllname = equipment.plcName();
    result = linkPLCDriver();   // Load PLC Manager's DLL
    if (result < 0)
    {
        return result;
    }

    string mmapPath = equipment.root() + DIR_SEPARATOR_STRING + _TX("shared");
    string plcConfig = equipment.root() + DIR_SEPARATOR_STRING + _TX("xml") + DIR_SEPARATOR_STRING + m_devxml;
    m_plcmngr->init(mmapPath.c_str(), plcConfig.c_str());

    //
    // Read plc data from xml file.
    //
    string xmlPath = equipment.root() + DIR_SEPARATOR_STRING + _TX("xml") + DIR_SEPARATOR_STRING + m_sacxml;
    SACXmlParser parser(xmlPath, this);
    result = equipment.xml().parseDom(parser, xmlPath);
    if (result < 0)
    {
        return result;
    }

    //
    // Link plc address and PLCDevice*
    //
    //## JGPLCDeviceTable::iterator iter = m_devs.begin();
    //## for ( ; iter != m_devs.end(); iter++)
    //## {
    //##     JGPLCDevice * plc = (*iter).second;
    //##     PLCDevice * physical = m_plc_mngr->get(plc->m_plc.type());
    //##     plc->m_plc.m_memory = physical;
    //## }

    return BEE_SUCCESS;
}


//-----------------------------------------------------------------------------
// Add new I/O Device
//-----------------------------------------------------------------------------
int JGPLCManager::add(JGPLCDevice& device)
{
    TRACE_FUNCTION(TRL_LOW, "JGPLCManager::add");

    JGPLCDevice * iodev = new JGPLCDevice(device);
    m_devs.insert(JGPLCDevicePair(iodev->devid(), iodev));
    m_devmap.insert(JGPLCNamePair(iodev->name(), iodev));

    return BEE_SUCCESS;
}

//-----------------------------------------------------------------------------
// Find the I/O Device
//-----------------------------------------------------------------------------
JGPLCDevice * JGPLCManager::find(JGid& devid)
{
    TRACE_FUNCTION(TRL_LOW, "JGPLCManager::find");

    JGPLCDevice * iodev;
    JGPLCDeviceTable::iterator iter = m_devs.find(devid);
    if (iter == m_devs.end())
    {
        return NULL;
    }
    iodev = (*iter).second;
    return iodev;
}

//-----------------------------------------------------------------------------
// Find the I/O Device by name
//-----------------------------------------------------------------------------
JGPLCDevice * JGPLCManager::findByName(const string& ioname)
{
    TRACE_FUNCTION(TRL_LOW, "JGPLCManager::findByName");

    JGPLCDevice * iodev;
    JGPLCDeviceMap::iterator iter = m_devmap.find(ioname);
    if (iter == m_devmap.end())
    {
        return NULL;
    }
    iodev = (*iter).second;
    return iodev;
}

