/*
 * Element.h
 *
 * Copyright (C) 1999 Stephen F. White
 * 
 * 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 (see the file "COPYING" for details); if 
 * not, write to the Free Software Foundation, Inc., 675 Mass Ave, 
 * Cambridge, MA 02139, USA.
 */

#ifndef _ELEMENT_H
#define _ELEMENT_H

#ifndef _DUNE_STRING_H
# include "MyString.h"
#endif

#include "Array.h"
#include "x3dFlags.h"

class Node;
class Proto;

enum {
    EL_UNKNOWN,

    EL_EVENT_IN,
    EL_EVENT_OUT,
    EL_EXPOSED_FIELD,
    EL_FIELD,

    EL_INITIALIZE,
    EL_EVENTS_PROCESSED,
    EL_SHUTDOWN
};

enum {
    FF_HIDDEN         = 1<<0,
    FF_FIXEDSTRINGS   = 1<<1,
    FF_URL            = 1<<2,
    FF_WONDERLAND_ART = 1<<3,
    FF_DOUBLE         = 1<<4,
    FF_3_DOUBLE       = 1<<5,
    FF_DELETED        = 1<<6,
    FF_STATIC         = 1<<7,
    FF_IN_SCRIPT      = 1<<8,
    FF_SCRIPT_URL     = 1<<9,
    FF_COVER_ONLY     = 1<<10,
    FF_KAMBI_ONLY     = 1<<11,
    FF_X3D_ONLY       = 1<<12,
    FF_VRML_ONLY      = 1<<13,
    FF_IS_NAME        = 1<<14,
    FF_IS             = 1<<15,
    EIF_IS            = 1<<16,
    EOF_IS            = 1<<17,
    EOF_IS_HIDDEN     = 1<<18,
    EIF_RECOMMENDED   = 1<<19,
    EOF_RECOMMENDED   = 1<<20
};

class IsElement {
public:
          IsElement() 
             { 
             _nodeIndex = -1; 
             _node = NULL; 
             _field = -1;
             _elementType = EL_UNKNOWN;
             _originalProto = NULL;
             _originalField = -1;
             }
          IsElement(Node *node, int field, int elementType, 
                    Proto *origProto, int origField) 
             { 
             _nodeIndex = -1; 
             _node = node; 
             _field = field; 
             _elementType = elementType;
             _originalProto = origProto;
             _originalField = origField;
             }
    Node* getNode(void)  { return _node; }
    int   getField(void) { return _field; }
    int   getElementType(void) { return _elementType; }
    int   getNodeIndex(void) { return _nodeIndex; }
    void  setNodeIndex(int nodeIndex) { _nodeIndex = nodeIndex; } 
protected:
    int    _nodeIndex;
    Node  *_node;
    int    _field;
    Proto *_originalProto;
    int    _originalField;
    int    _elementType;
};

class Element {
public:
    virtual            ~Element() {}
    virtual int         getElementType() const = 0;
    virtual const char *getElementName(bool x3d) const = 0;
    const MyString     &getName(bool x3d) const;
    int                 getType() const { return _type; }

    int                 getFlags() const { return _flags; }
    void                setFlags(int flags) { _flags = flags; }
    void                addFlags(int flags) { _flags |= flags; }
    void                removeFlags(int flags) 
                           { _flags = _flags & !(flags & 0xffff); }

    virtual int         write(int filedes, int indent, int flag = 0) 
                              const = 0;
    virtual int         writeElementPart(int filedes, int indent, int flag) 
                                         const;

    void                addIs(Node *node, int field, int elementType,
                              Proto *origProto, int origField, int flags = 0);
    int                 getNumIs(void) { return _isArray.size(); }
    Node               *getIsNode(int i) { return _isArray[i]->getNode(); }
    int                 getIsField(int i) { return _isArray[i]->getField(); }
    int                 getIsElementType(int i) 
                           { return _isArray[i]->getElementType(); }
    int                 getIsNodeIndex(int i) 
                           { return _isArray[i]->getNodeIndex(); }
    void                setIsNodeIndex(int i, int nodeIndex) 
                           { _isArray[i]->setNodeIndex(nodeIndex); }

    void                setAppinfo(const MyString& appinfo) 
                           { _appinfo = appinfo; } 
    MyString            getAppinfo() const 
                           { return _appinfo; } 
    void                setDocumentation(const MyString& documentation) 
                           { _documentation = documentation; } 
    MyString            getDocumentation() const 
                           { return _documentation; } 
protected:
    int                 _type;
    MyString            _name;
    MyString            _x3dName;
    int                 _flags;
    Array<IsElement *>  _isArray;

    MyString            _appinfo;
    MyString            _documentation;
};

int indentf(int filedes, int indent);

#endif // _ELEMENT_H
