// $Id: JGLimit.h,v 1.6 2003/03/16 14:51:00 fukasawa Exp $

//=============================================================================
/**
 *  @file    JGLimit.h
 *
 *  @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.
 */
//=============================================================================

#ifndef JGLIMIT_H
#define JGLIMIT_H

#include "JGNameInfo.h"
#include "JGVariable.h"
#include "BS2TimeValue.h"

const int MIN_LIMITID = 1;
const int MAX_LIMITID = 7;

class BS2ListItem;
class BS2Message;
class JGLimitBorder;

typedef vector<class JGLimitBorder>  JGLimitBorderSet;

//
// Define an object to hold configure data
//
class JGLimit : public JGNameVarInfo
{
    friend class JGLimitManager;

public:
    enum { TRANSITION_NONE = -1, TRANSITION_LOWER = 0, TRANSITION_UPPER = 1 };

    JGLimit() : JGNameVarInfo(), m_unit(_TX("")),
                m_limitid(0), m_transition(TRANSITION_NONE), m_maxval(0),
                m_minval(0), m_enabled(false) {}
    JGLimit(JGid& vid) : JGNameVarInfo(), m_unit(_TX("")),
                         m_limitid(0), m_transition(TRANSITION_NONE),
                         m_maxval(0), m_minval(0),
                         m_enabled(false) { m_vid = vid; }
    virtual ~JGLimit() {}
    virtual void printOn(string& buf, int mode = 0);

    JGLimit& operator=(const JGLimit& rhs);
    void insert(JGLimitBorder& border) { m_borders.push_back(border); }

    JGid& ceid()               { return m_id; }
    void  ceid(JGid& id)       { m_id = id;  m_id.get(m_name); }
    bool enabled() const       { return m_enabled; }
    bool defined() const       { return m_defined; }
    void enabled(bool enabled) { m_enabled = enabled; }
    void defined(bool defined) { m_defined = defined; }
    void manager(JGLimitManager * mngr) { m_manager = mngr; }
    void sort();
    JGLimitBorderSet& limitBorders() { return m_borders; }
    JGLimitBorder * find(int limid);

    int transition(JGvalue& last, JGvalue& current);
    BS2ListItem * checkNewBorders(JGLimit& req);  // Check defined limit attributes in S2F45
    int updateNewBorders(JGLimit& req);           // Update limit attributes in S2F45
    BS2Item * attributeItem();          // for S2F48
    BS2Item * ceidItem(int format);     // for S6F11
    BS2Atom * getAtom(const string& varName);

protected:
    string m_unit;
    //
    JGLimitManager * m_manager;
    bool m_defined;                 // defined limit attributes
    JGLimitBorderSet m_borders;     // limit border list
    int  m_limitid;                 // recent limitted id
    int  m_transition;
    JGvalue m_maxval;               // max value
    JGvalue m_minval;               // min value
    bool m_enabled;
    int  m_trnum;                   // transit zone count
    BYTE m_ids[MAX_LIMIT_ZONE];     // transit limit ids
    BS2TimeValue m_tv;              // recent transit zone time
};

//
// Limit DeadBand infomation
//
class JGLimitBorder
{
    friend class JGLimit;
    friend class JGLimitManager;
    friend struct comp_border;

public:
    JGLimitBorder() : m_vid(0), m_limid(0), m_enabled(false), m_upval(0),
                      m_lowval(0), m_lastTransition(JGLimit::TRANSITION_NONE) {}
    JGLimitBorder(JGid& id, int limid)
            : m_vid(id), m_limid(limid), m_enabled(false), m_upval(0),
              m_lowval(0), m_lastTransition(JGLimit::TRANSITION_NONE) {}

    JGLimitBorder& operator=(const JGLimitBorder& rhs);

    void vid(JGid& id)   { m_vid = id; }
    JGid& vid()          { return m_vid; }
    int   limitId()      { return m_limid; }
    JGvalue& upperdb()   { return m_upval; }
    JGvalue& lowerdb()   { return m_lowval; }
    bool enabled() const { return m_enabled; }
    void upperdb(JGvalue& upv)  { m_upval = upv; }
    void lowerdb(JGvalue& lowv) { m_lowval = lowv; }
    void enabled(bool enabled)  { m_enabled = enabled; }

    int transition(JGvalue& last, JGvalue& current);
    BS2Item * attributeItem();             // for S2F48

protected:
    JGid m_vid;
    int  m_limid;
    //
    bool m_enabled;
    JGvalue m_upval;
    JGvalue m_lowval;
    int     m_lastTransition;
};

// Compare Limit Borders
struct comp_border
{
    bool operator() (const JGLimitBorder& x, const JGLimitBorder& y) const
    {
        return (x.m_upval < y.m_upval);
    }
};

//
typedef map<JGid, JGLimit, id_less, allocator<JGLimit> > JGLimitTable;
typedef JGLimitTable::value_type  JGLimitPair;
typedef vector<JGLimit>   JGLimitArray;
typedef vector<JGLimit *> JGLimits;
typedef list<JGLimit *>   JGLimitList;

#endif  /* JGLIMIT_H */
