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

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


// $Log:	BaseCI.h,v $
// Revision 1.2  93/05/27  11:19:16  thoth
// Copyright Notices
// 
// Revision 1.1  93/05/26  17:14:51  thoth
// Initial revision
// 

#ifndef BaseCI_h_
#define BaseCI_h_

#include <iostream.h>
//#include <stdlib.h>
#include "ia.h"
#include "FloatPoint.h"
#include "FloatPointSet.h"
#include "ValueSet.h"

typedef const char* const IA_ImageType;

template <class T> class IA_ContinuousImage;

#if 0
template <class T, class P, class PS>
class IA_BaseImage {
protected:
    PS ps;

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


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

    IA_BaseImage(const PS &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 P &) 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 P &);

    // Each class derived from BaseImage must support the member function
    // type which returns a ContinuousImageType 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_ImageType type() const = 0;

    virtual ~IA_BaseImage() {};

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

    PS 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_BaseImage *restricted_to(const PS &) const;

    virtual IA_BaseImage *xlated_by(const P &) const;

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

    friend class IA_ContinuousImage<T>;
};


// there is no way to curry out template arguments
template <class T>
class IA_BaseCI: public IA_BaseImage<T, IA_FloatPoint, IA_FloatPointSet>{
};

#else

template <class T>
class IA_BaseCI {
protected:
    IA_FloatPointSet ps;

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


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

    IA_BaseCI(const IA_FloatPointSet &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_FloatPoint &) const =0;

#if 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_FloatPoint &);
#endif

    // Each class derived from BaseCI must support the member function
    // type which returns a ContinuousImageType 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_ImageType type() const = 0;

    virtual ~IA_BaseCI() {};

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

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

#if 0
    // 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_BaseCI *restricted_to(const IA_FloatPointSet &) const;

    virtual IA_BaseCI *xlated_by(const IA_FloatPoint &) const;

    virtual ostream& print_this(ostream&) const = 0;
#endif

    friend ostream& operator <<(ostream&, const IA_BaseCI<T>&);

    friend class IA_ContinuousImage<T>;
};


#endif

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

#endif
