/****************************************************************************/
/* Copyright (c) 2000 MBARI                                                 */
/* MBARI Proprietary Information. All rights reserved.                      */
/****************************************************************************/
/* Summary  :                                                               */
/* Filename : idl.h                                                         */
/* Author   : Tom O'Reilly                                                  */
/* Project  :                                                               */
/* Version  : 1.0                                                           */
/* Created  : 02/07/2000                                                    */
/* Modified :                                                               */
/* Archived :                                                               */
/****************************************************************************/
/* Modification History:                                                    */
/****************************************************************************/
#ifndef _IDL_H
#define _IDL_H

#ifdef _QNX
  typedef unsigned char bool;
# define true 1
# define false 0  
#endif

#include "DynamicArray.h"

class Comment {

public:

  Comment(const char *text);
  ~Comment();

  const char *text();

protected:

  char *_text;
};


enum DataType {
  FloatType,
  DoubleType,
  ShortType,
  LongType,
  UnsignedShortType,
  UnsignedLongType,
  UnsignedCharType,
  CharType,
  BooleanType,
  VoidType,
  StructureType,
  EnumerationType,
  SequenceType,
  InterfaceType
};


// Forward declarations
class DataInstance;
class Context;
class Interface;

class Base {

public:
  Base(const char *name, Context *contex = 0);
  ~Base();

  const char *name();

  Context *context;

  DynamicArray<Comment *> comments;

protected:

  const char *_name;
};


class DataDefinition : public Base {

public:

  DataDefinition(const char *name, DataType dataType, Context *context);
  ~DataDefinition();

  virtual DataType dataType();

  // Interface in which this is defined
  Interface *definingInterface();

private:

  DataType _dataType;
};



class Primitive : public DataDefinition {

public:

  Primitive(DataType dataType, Context *context);
  ~Primitive();
};

class Structure;
class Enumeration;
class Sequence;

class Context : public DataDefinition {

public:

  Context(const char *name, DataType dataType, Context *context, 
	  Context *parentClass);

  ~Context();

  DynamicArray<Structure *> structures;
  DynamicArray<Enumeration *> enumerations;
  DynamicArray<Sequence *> sequences;

  // Class (i.e., Context) from which this is subclassed
  Context *parentClass;
};



class Enumeration : public DataDefinition {

public:

  Enumeration(const char *name, Context *context);
  ~Enumeration();

  class Value : public DataDefinition {

    friend class Enumeration;

  public:

    bool defaultValue();
    int value();

  protected:

    Value(const char *name, Context *context, 
	  bool defaultValue = true, int value = 0); 

    ~Value();


    bool _defaultValue;
    int _value;
  };

  void addValue(const char *name, bool defaultValue = true, int value = 0);

  DynamicArray<Enumeration::Value *> values;
};


class Sequence : public DataDefinition {

public:

  Sequence(const char *name, DataDefinition *element, int maxElements, 
	   Context *context);

  ~Sequence();

  int maxElements();

  DataDefinition *element;


protected:

  int _maxElements;
};


class Structure : public Context {

public:

  Structure(const char *name, Context *context, Structure *parentClass = 0);
  ~Structure();

  // Struct can contain data instances
  DynamicArray<DataInstance *> instances;

};



class DataInstance : public Base {

public:

  DataInstance(const char *name, DataDefinition *dataDefinition, 
	       Context *context);

  ~DataInstance();

  DataDefinition *dataDefinition;
};


class Method : public Base {

public:

  Method(const char *name, DataDefinition *returnObject,
	 unsigned overloadCount = 0);

  ~Method();


  enum IoSpecifier {
    In, Out, InOut
  };

  class Argument : public DataInstance {

    friend class Method;

  public:

    Argument(const char *name, DataDefinition *definition, IoSpecifier io,
	     Context *context);

    ~Argument();

    IoSpecifier io();

  protected:

    IoSpecifier _io;
  };


  void addArgument(const char *name, 
		   DataDefinition *dataDefinition, 
		   IoSpecifier io);

  DynamicArray<Argument *> arguments;

  unsigned overloadCount();

  DataDefinition *returnObject;

protected:

  unsigned _overloadCount;
};


class Interface : public Context {

public:

  Interface(const char *name, Context *context, Interface *parentClass = 0);

  ~Interface();

  // Interface contains methods
  DynamicArray<Method *> methods;

  DynamicArray<Interface *> referencedInterfaces;
};


bool primitiveType(DataType dataType);
bool aggregateType(DataType dataType);

#endif
