/*************************************************************************
 *    CompuCell - A software framework for multimodel simulations of     *
 * biocomplexity problems Copyright (C) 2003 University of Notre Dame,   *
 *                             Indiana                                   *
 *                                                                       *
 * This program is free software; IF YOU AGREE TO CITE USE OF CompuCell  *
 *  IN ALL RELATED RESEARCH PUBLICATIONS according to the terms of the   *
 *  CompuCell GNU General Public License RIDER you can redistribute it   *
 * and/or modify it under the terms of the GNU General Public License as *
 *  published by the Free Software Foundation; either version 2 of the   *
 *         License, or (at your option) any later version.               *
 *                                                                       *
 * This program is distributed in the hope that it will be useful, but   *
 *      WITHOUT ANY WARRANTY; without even the implied warranty of       *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU    *
 *             General Public License for more details.                  *
 *                                                                       *
 *  You should have received a copy of the GNU General Public License    *
 *     along with this program; if not, write to the Free Software       *
 *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.        *
 *************************************************************************/

#include "OgleVizDumper.h"

#include <CompuCell3D/Simulator.h>
#include <CompuCell3D/ClassRegistry.h>
#include <CompuCell3D/Viz/FieldRenderer.h>
#include <CompuCell3D/Field3D/Field3D.h>
#include <CompuCell3D/Potts3D/Potts3D.h>
#include <CompuCell3D/Potts3D/Cell.h>
using namespace CompuCell3D;

#include <XMLCereal/XMLPullParser.h>
#include <XMLCereal/XMLSerializer.h>

#include <BasicUtils/BasicString.h>

using namespace std;

#include <stdio.h>

#include <config.h>
#ifdef HAVE_ZLIB
#include <zlib.h>
#define ZOPEN  gzopen
#define ZPUTC  gzputc
#define ZPUTS  gzputs
#define ZFILE  gzFile
#define ZCLOSE gzclose
#define SUFFIX ".dat.gz"
#else
#define ZOPEN  fopen
#define ZPUTC(file, c)  putc(c, file)
#define ZPUTS(file, s)  puts(s, file)
#define ZPUTC(file,c)  fputc(c,file)
#define ZPUTS(file,s)  fputs(s,file)
#define ZFILE  FILE *
#define ZCLOSE fclose
#define SUFFIX ".dat"
#endif

void OgleVizDumper::step(const unsigned int currentStep) {
  ASSERT_OR_THROW("dumpVizField() No renderer set!", renderer);

  Dim3D dim = renderer->getDim();

  char buf[512];
  sprintf(buf, "%ix%ix%i-%i-%c%c%c%c", dim.x, dim.y, dim.z, 1,
	  'c', 'u', 'o', 'n');

  string prefix =  BasicString(currentStep);
  if (filePrefix != "") prefix = filePrefix + "-" + prefix;
  string redFilename = prefix + "-red-" + buf + SUFFIX;
  string greenFilename = prefix + "-grn-" + buf + SUFFIX;
  string blueFilename = prefix + "-blu-" + buf + SUFFIX;
  string opacityFilename = prefix + "-opc-" + buf + SUFFIX;

  ZFILE redFile = ZOPEN(redFilename.c_str(), "w");
  ZFILE greenFile = ZOPEN(greenFilename.c_str(), "w");
  ZFILE blueFile = ZOPEN(blueFilename.c_str(), "w");
  ZFILE opacityFile = ZOPEN(opacityFilename.c_str(), "w");

  Point3D pt;
  VizProperties props;
  for (pt.z = 0; pt.z < dim.z; pt.z++)
    for (pt.y = 0; pt.y < dim.y; pt.y++)
      for (pt.x = 0; pt.x < dim.x; pt.x++) {
	props = renderer->get(pt);
	
	
	ZPUTC(redFile, (unsigned char)props.red);
	ZPUTC(greenFile, (unsigned char)props.green);
	ZPUTC(blueFile, (unsigned char)props.blue);
	ZPUTC(opacityFile, (unsigned char)props.opacity);

      
      }

  ZPUTS(redFile, "MIN 0 MAX 255\n");
  ZPUTS(greenFile, "MIN 0 MAX 255\n");
  ZPUTS(blueFile, "MIN 0 MAX 255\n");
  ZPUTS(opacityFile, "MIN 0 MAX 255\n");
  

  ZCLOSE(redFile);
  ZCLOSE(greenFile);
  ZCLOSE(blueFile);
  ZCLOSE(opacityFile);
}



void OgleVizDumper::readXML(XMLPullParser &in) {
  in.skip(TEXT);

  while (in.check(START_ELEMENT)) {
    if (in.getName() == "FilePrefix") {
      filePrefix = BasicString::trim(in.matchSimple());

    } else if (in.getName() == "Renderer") {
      ClassRegistry *reg = simulator->getClassRegistry();
      renderer = reg->getRenderer(BasicString::trim(in.matchSimple()));

    } else {
      throw BasicException(string("Unexpected element '") + in.getName() + 
			   "'!", in.getLocation());
    }

    in.skip(TEXT);
  }

  ASSERT_OR_THROW("You must set a Renderer!", renderer);
}

void OgleVizDumper::writeXML(XMLSerializer &out) {
}
