/*
** (c) 1996-2000 The Regents of the University of California (through
** E.O. Lawrence Berkeley National Laboratory), subject to approval by
** the U.S. Department of Energy.  Your use of this software is under
** license -- the license agreement is attached and included in the
** directory as license.txt or you may contact Berkeley Lab's Technology
** Transfer Department at TTD@lbl.gov.  NOTICE OF U.S. GOVERNMENT RIGHTS.
** The Software was developed under funding from the U.S. Government
** which consequently retains certain rights as follows: the
** U.S. Government has been granted for itself and others acting on its
** behalf a paid-up, nonexclusive, irrevocable, worldwide license in the
** Software to reproduce, prepare derivative works, and perform publicly
** and display publicly.  Beginning five (5) years after the date
** permission to assert copyright is obtained from the U.S. Department of
** Energy, and subject to any subsequent five (5) year renewals, the
** U.S. Government is granted for itself and others acting on its behalf
** a paid-up, nonexclusive, irrevocable, worldwide license in the
** Software to reproduce, prepare derivative works, distribute copies to
** the public, perform publicly and display publicly, and to permit
** others to do so.
*/

#include <string>

#include <Contour.H>
#include <ParmParse.H>
#include <globals.H>

#ifdef HAS_WINDOWS

// ************************************************************************
// ** constructor **
// ************************************************************************

Contour::Contour(){
    first = NULL;
    ParmParse pp("contour");
    int n = pp.countname("plot");
    for (int k = 0; k < n; k++) {
	int freq = -1;
	pp.getkth("plot",k,freq,3);
	if (freq > 0) {
	    std::string fname, varname;
	    int dev, nc, sz;
	    pp.getkth("plot",k,fname,0);
	    pp.getkth("plot",k,dev,1);
	    pp.getkth("plot",k,varname,2);
	    pp.getkth("plot",k,nc,4);
	    pp.getkth("plot",k,sz,5);
	    ContFrame *cf= new ContFrame(fname,varname,dev,freq,nc,sz);
	    cf->next = first;
	    first = cf;
	}
    }
}

// ************************************************************************
// ** destructor **
// ************************************************************************

Contour::~Contour()
{
    clear();
}

// ************************************************************************
// ** clear **
// ************************************************************************

void Contour::clear()
{
    ContFrame *cont = first;
    while (cont != NULL) {
	ContFrame *c = cont;
	cont = cont->next;
	c->next = NULL;
	delete c;
    };
}

// ************************************************************************
// ** << **
// ************************************************************************

std::ostream& operator << (std::ostream &os, Contour &cont)
{
    ContFrame *c;
    for (c=cont.first; c!=NULL; c=c->next) {
	os << "contplot  " << c->name << "  " << c->device << "  " 
           << c->variable << "  " << c->interval
	   << "  " << c->num_cont << "  " << std::endl;
    };
    return os;
}

// ************************************************************************
// ** drawCont **
// ************************************************************************

void Contour::drawCont(Grid &grid, int nstep, Real time)
{
      // loop through frames, creating and writing images

    ContFrame *r;

    for (r = first; r != NULL; r = r->next) {

	if ((r->interval > 0) && (nstep%(r->interval) == 0)) {

	      // Added by ASA and EGP to create new PS files each time step.

	    char filename[80];
	    const char* rootname = (r->name).c_str();
	    sprintf(filename,"%s%04d",rootname,nstep);

	    const Real* dx = grid.cellSize();
	    const Real* prob_size = grid.probSize();

	      // if window not created yet, create it
	    if (r->win == NULL) {
		double xborder = dx[0];
		double yborder = dx[1];
		double xmax = prob_size[0]+xborder;
		double ymax = prob_size[1]+yborder;
		r->win = new GraphTool(-xborder,-yborder,xmax,ymax,
				       filename,r->size,r->device);
	    };

	      // clear page before drawing

	    r->win->newPage();

	      // derive data and compute min and max

	    Box bx(grid.probDomain());
	    const IntVect len = bx.length();
	    FArrayBox data(bx,1);
	    grid.deriveData(data,r->variable,time);
	    double v_min = data.min(0);
	    double v_max = data.max(0);

	      // check for constant field

	    if ( (v_max-v_min) < 0.0001) {
		std::cout << r->variable << " is a constant with value "
		     << v_min << " ... will not plot" << std::endl;
	    } else {
		std::cout << r->variable << " has min = " << v_min
		     << " max = " << v_max << std::endl;

		double d_val = (v_max-v_min)/double(r->num_cont);

		double xborder = dx[0];
		double yborder = dx[1];
		double xmax = prob_size[0]+xborder;
		double ymax = prob_size[1]+yborder;

		Real xtop = prob_size[0];
		Real ytop = prob_size[1];
		if (r->device == psDevice) {
		    xtop = 0.5*prob_size[0];
		    ytop = 0.5*prob_size[1];
		}

		if (r->device == psDevice) {
		    r->win->drawBox(-.5*xborder,-.5*yborder,.5*xmax,.5*ymax);
		} else {
		    r->win->drawBox(-xborder,-yborder,xmax,ymax);
		}

		  // draw contour plot
		const int* mask_array = NULL;
		for (int i = 0; i < r->num_cont; i++) {
		    double value = v_min + d_val*(0.5 + double(i));
		    r->win->contour(data.dataPtr(),value,false,mask_array,
				    len[0],len[1],len[0],len[1],
				    0.0,0.0,xtop,ytop);
		}
	    }

	    if (r->device == psDevice) {
		delete r->win;
		r->win = NULL;
	    }
	 
	}
    }
   
}

bool Contour::doingContour()
{
  bool is_doing_contour = false;
  ContFrame *r;

  for (r = first; r != NULL; r = r->next) {
    if (r->interval > 0) {
      is_doing_contour = true;
    }
  }

  return is_doing_contour;
}
#endif
