// Emacs: -*- C++ -*-

//
//	Copyright 1993, Center for Computer Vision and Visualization,
//	University of Florida.  All rights reserved.
//


// $Log:	BaseDI.h,v $
// Revision 1.12  93/05/27  11:19:24  thoth
// Copyright Notices
// 
// Revision 1.11  93/05/18  21:38:45  thoth
// range method returns ValueSet again.
// new value_array method gives an Array of image values.
// 
// 
// Revision 1.10  93/04/17  18:44:57  thoth
// Iterator support is no longer based on a switch statement.  We now
// use a virtual method.  The user can now provide faster iterators.
// 
// Revision 1.9  93/04/08  13:05:08  thoth
// restriction to a pointset and translation by a point are
// now virtual methods.
// 
// Revision 1.8  93/03/10  13:31:23  thoth
// range method no longer returns valueset due to
// difficulties with template implementation.
// 
// Revision 1.7  93/02/23  14:04:59  thoth
// clone_self_extensively and range now have default versions.
// 
// Revision 1.6  93/02/20  12:28:08  thoth
// Refcounting procedures are no longer virtual since we redid the
// ErrorDI mechanism.
// Cleaned up some #if 1s.
// Equality testing does not belong in BaseDI or derived classes.
// 
// Revision 1.5  93/02/08  11:31:54  thoth
// refcount consistency is now enforced.  Derived classes should not worry
// about it any more.
// 
// Revision 1.4  93/01/19  14:55:33  jnw
// Modified to support IA_ naming convention
// 
// Revision 1.3  92/11/14  09:32:47  jnw
// got rid of val and ref and substituted () and [] with int argument
// These may be extraneous (they aren't used right now).  It seems that
// whenever one wants to get at the storage order of a BaseDI, they already
// know what the underlying derived type is.  I'll leave them in however,
// because it's always possible we'll add some new extensive representations.
// 
// Revision 1.2  92/11/13  13:49:29  jnw
// Updated to include all sorts of new goodies
// 
// Revision 1.1  92/10/05  11:43:11  jnw
// Initial revision
// 

#ifndef BaseDI_h_
#define BaseDI_h_

#include <iostream.h>
//#include <stdlib.h>
#include "ia.h"
#include "IntPoint.h"
#include "IntPointSet.h"
#include "ValueSet.h"

typedef const char* const IA_DiscreteImageType;

template <class T> class IA_DiscreteImage;
template <class T> class IA_BaseDIVIter;
template <class T> class IA_BaseDIPIter;


template <class T>
class IA_BaseDI{
protected:
    IA_IntPointSet ps;

    // refcount counts the number of references to this BaseDI object
    //   from DiscreteImage container class objects.
    // It is maintained by container classes.
    int refcount;


public:
    // Constructor for BaseDI takes care of initting the refcount.
    // Derived classes need not frob it.
    // It is the responsibility of the container to maintain the refcount!

    IA_BaseDI(const IA_IntPointSet &p):ps(p) {
	refcount = 0;
    }

    int get_ref() { return refcount; }
    int incr_ref() { return ++refcount; }
    int decr_ref() { return --refcount; }

    // If the following method returns nonzero, then operator[]
    // is meaningful and clone_self_extensively is not necessary
    // unless the image is shared.
    virtual int extensivep() const =0;

    // For the next two functions, we expect our container to trap
    // out-of-bounds points
    virtual T operator ()(const IA_IntPoint &) const =0;

    // This method returns a modifiable reference to a value in the
    // image.  It should not be called for objects that return
    // extensivep()==0.  Modifying through the reference returned
    // alters the image, so make sure the image is not shared.
    virtual T& operator [](const IA_IntPoint &);

    // Each class derived from BaseDI must support the member function
    // type which returns a DiscreteImageType value (a pointer to an int).
    // To distinguish between the different classes derived from BaseDI,
    // we make certain that type will be distinct for each of these classes
    // as follows:
    //	Each class derived from BaseDI defines a static function member dummy:
    //		static int dummy;
    //  The class definition for derived class "classname" must also be
    //	followed by a declaration of form
    //		template <class T> int classname<T>::dummy = 0;
    //	The member function type() in each class derived from BaseDI returns
    //	the address of dummy.
    // Thus each class returns a unique value for a call of type().

    virtual IA_DiscreteImageType type() const = 0;

    virtual ~IA_BaseDI() {};

    // The default version of this is not blazingly fast.
    // If you can do faster in a specific implementation, please do.
    virtual IA_BaseDI* clone_self_extensively() const;

    IA_IntPointSet domain() const { return this->ps; }

    // The default version of this is not blazingly fast.
    // If you can do faster in a specific implementation, please do.
    virtual IA_ValueSet<T> range() const;

    virtual IA_Array<T> value_array() const;

    virtual IA_BaseDI *restricted_to(const IA_IntPointSet &) const;

    virtual IA_BaseDI *xlated_by(const IA_IntPoint &) const;

    virtual IA_BaseDIVIter<T> *value_iterator() const;
    virtual IA_BaseDIPIter<T> *pixel_iterator() const;

    virtual ostream& print_this(ostream&) const = 0;
    
    friend ostream& operator <<(ostream&, const IA_BaseDI<T>&);

    friend class IA_DiscreteImage<T>;
};

template <class T>
ostream& operator <<(ostream&, const IA_BaseDI<T>&);

#endif
