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

#include "fitsimage.h"
#include "block.h"
#include "context.h"

void FitsImage::block()
{
  if (manageBlock_) {
    if (block_)
      delete block_;
    if (blockdata_)
      delete blockdata_;
  }
  manageBlock_ =0;
  block_ = base_;
  blockdata_ = basedata_;

  Vector blockFactor = parent->currentContext->blockFactor();
  Matrix mm = Scale(1/blockFactor[0],1/blockFactor[1]);

  if (blockFactor[0] != 1 && blockFactor[1] != 1) {
    block_ = new FitsBlock(base_, blockFactor);
    if (block_->isValid()) {
      manageBlock_ =1;

      int srcw = base_->head()->naxis(0);
      int srch = base_->head()->naxis(1);
      int ww = block_->head()->naxis(0);
      int hh = block_->head()->naxis(1);

      switch (block_->head()->bitpix()) {
      case -64:
	{
	  blockdata_ = new FitsDatam<double>(block_, parent);
	  double* dest=(double*)block_->data();
	  for (int jj=0; jj<srch; jj++) {
	    for (int ii=0; ii<srcw; ii++) {
	      Vector cc = Vector(ii,jj)*mm;
	      if (cc[0]>=0 && cc[0]<ww && cc[1]>=0 && cc[1]<hh) {
		double vv = basedata_->getValueDouble(jj*srcw+ii);
		*(dest+(int(cc[1])*ww + int(cc[0]))) += vv;
	      }
	    }
	  }
	}
	break;
      default:
	{
	  blockdata_ = new FitsDatam<float>(block_, parent);
	  float* dest=(float*)block_->data();
	  for (int jj=0; jj<srch; jj++) {
	    for (int ii=0; ii<srcw; ii++) {
	      Vector cc = Vector(ii,jj)*mm;
	      if (cc[0]>=0 && cc[0]<ww && cc[1]>=0 && cc[1]<hh) {
		float vv = basedata_->getValueFloat(jj*srcw+ii);
		*(dest+(int(cc[1])*ww + int(cc[0]))) += vv;
	      }
	    }
	  }
	}
	break;
      }
    }
    else {
      delete block_;
      block_ = base_;
      return;
    }
  }
}

Matrix FitsImage::updateBlock()
{
  // reset LTMV keywords
  keyLTMV = 0;

  // reset scanmode
  parent->resetScanMode();
  load();

  // only physicalToImage has been updated by load()
  // so map from old ref to new ref
  return refToPhysical * physicalToImage * imageToData * dataToRef;
}
