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

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


//
// $Log: BaseI.h,v $
// Revision 1.6  1994/07/25  17:24:13  thoth
// Name sanitization
//
// Revision 1.5  1994/03/14  15:48:33  thoth
// ValueSet has been replaced by container class Set.
//
// Revision 1.4  1994/02/26  16:02:08  thoth
// operator() of the container now relies upon the contained classes
// to check if p is contained in the domain.  This means that users
// could possibly write an erroneous operator().
//
// Revision 1.3  1994/01/07  15:12:35  thoth
// Image class is now CoreImage and named image types are
// Image<P,T>.
//
// Revision 1.2  1993/11/17  18:11:39  thoth
// extensivep is now extensive
//
// Revision 1.1  1993/09/15  12:50:22  thoth
// Initial revision
//

#ifndef BaseI_h_
#define BaseI_h_

#include <iostream.h>
#include "ia.h"
#include "Point.h"
#include "Set.h"


template <class P,class T> class IA_CoreImage;
template <class P,class T> class IA_BaseIVIter;
template <class P,class T> class IA_BaseIPIter;

template < class P,class T>
class IA_BaseImage {
  protected:
    IA_Set<P>	ps;
    
    // refcount counts the number of references to this BaseI object
    //   from Image container class objects.
    // It is maintained by container classes.
    int refcount;

public:
    // Constructor for BaseI 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 IA_Set<P> &ps_) : ps(ps_) {
	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 extensive() const =0;

    // For the next two functions, we must personally 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
    // extensive()==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 ImageType value (a pointer to an int).
    // To distinguish between the different classes derived from BaseImage,
    // we make certain that type will be distinct for each of these classes
    // as follows:
    //	Each class derived from BaseImage 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 BaseImage returns
    //	the address of dummy.
    // Thus each class returns a unique value for a call of type().

    virtual IA::Type 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;

    IA_Set<P> 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_Set<T> range() const;

    virtual IA_Array<T> value_array() const;

    virtual IA_BaseImage<IA_Point<int>,T> * restricted_to
    (const IA_Set<IA_Point<int> > &) const;
    virtual IA_BaseImage *restricted_to(const IA_Set<IA_Point<double> > &) const;

    virtual IA_BaseImage *xlated_by(const P &) const;

    virtual IA_BaseIVIter<P,T> *value_iterator() const;
    virtual IA_BaseIPIter<P,T> *pixel_iterator() const;

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

    friend class IA_CoreImage<P,T>;
};

#endif // BaseI_h_
