// Copyright (C) 1999-2014
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"

#ifndef __context_h__
#define __context_h__

#include "base.h"
#include "coord.h"
#include "frscale.h"
#include "list.h"
#include "fitsmask.h"
#include "fitsimage.h"

class FVContour;

class Context {
 public:
  enum SmoothFunction {BOXCAR, TOPHAT, GAUSSIAN};

  FitsImage* fits;
  FitsImage* cfits;

  List <FitsMask> mask;

  FVContour* contour;
  List<Contour> auxcontours;

  FrScale frScale;

 private:
  Base* parent_;

  int mosaicCount_;
  int naxis_[FTY_MAXAXES]; // the first two are ignored
  int slice_[FTY_MAXAXES]; // the first two are ignored

  Base::MosaicType mosaicType;
  Coord::CoordSystem mosaicSystem;

  FitsHist::Function binFunction_;
  Vector binFactor_;
  int binBufferSize_;
  int binDepth_;

  int doBlock_;
  Vector blockFactor_;

  int doSmooth_;
  SmoothFunction smoothFunction_;
  int smoothRadius_;

  int nhdu();
  void updateClip(FrScale*);

 public:
  Context();
  ~Context();
  Context(const Context&);
  Context& operator=(const Context&);

  void render(FitsImage::RenderStage);

  void bltHist(char*, char*, int);

  int calcSlice();
  void clearContour();
  void contourAuxHead() {auxcontours.head();}
  void contourAuxNext() {auxcontours.next();}

  int fitsCount();

  Vector getClip(FrScale::ClipMode, float);
  Vector getClip();

  int hasContour() {return contour ? 1 : 0;}
  int hasContourAux() {return auxcontours.current() ? 1 : 0;}
  double* histequ() {return frScale.histequ(fits);}

  int isMosaic() {return mosaicCount_>1 ? 1 : 0;}
  int isCube() {return nhdu()>1 ? 1 : 0;}

  int load(Base*, Base::MemType, const char*, FitsImage*, Base::LayerType);
  int loadExtCube(Base*, Base::MemType, const char*, FitsImage*);
  int loadSlice(Base*, Base::MemType, const char*, FitsImage*);
  int loadMosaic(Base*, Base::MemType, const char*, FitsImage*, 
		 Base::LayerType, Base::MosaicType, Coord::CoordSystem);
  int loadMosaicImage(Base*, Base::MemType, const char*, FitsImage*, 
		      Base::LayerType, Base::MosaicType, Coord::CoordSystem);
  int loadMosaicWFPC2(Base*, Base::MemType, const char*, FitsImage*);
  void loadInit(Base::MosaicType, Coord::CoordSystem);
  void loadFinish();
  void loadFinishMask();

  int naxis(int ii) {return naxis_[ii];}
  int naxes();

  void parent(Base* pp) {parent_ = pp;}

  void setContour(FVContour*);
  int slice(int ii) {return slice_[ii];}

  void setBinFunction(FitsHist::Function f) {binFunction_ = f;}
  void setBinFactor(const Vector&);
  void setBinToFactor(const Vector&);
  void setBinBufferSize(int s) {binBufferSize_ = s;}
  void setBinDepth(int d) {binDepth_ = d < 1 ? 1 : d;}
  FitsHist::Function binFunction() {return binFunction_;}
  Vector binFactor() {return binFactor_;}
  int binBufferSize() {return binBufferSize_;}
  int binDepth() {return binDepth_;}

  void setBlock(int bb) {doBlock_ =bb;}
  void setBlock(int bb, const Vector& ff)
  {doBlock_ =bb; blockFactor_ =ff;}
  int hasBlock() {return doBlock_;}
  const Vector& blockFactor() {return blockFactor_;}

  void setSmooth(int ss) {doSmooth_ =ss;}
  void setSmooth(int ss, SmoothFunction ff, int rr)
  {doSmooth_=ss; smoothFunction_=ff; smoothRadius_=rr;}
  int hasSmooth() {return doSmooth_;}
  SmoothFunction smoothFunction() {return smoothFunction_;}
  int smoothRadius() {return smoothRadius_;}

  void unload();
  void updateBin(Base*);
  void updateBinFileNames();
  void updateClip();
  void updateContours();
  void updateContours(const Matrix&);
  void updateSlice(int, int);
};

#endif
