/**********************************************************************
* 
* cell_01_Prophase.cpp
*
* This file is part of MitoGen
* 
* Copyright (C) 2013-2016 -- Centre for Biomedical Image Analysis (CBIA)
* http://cbia.fi.muni.cz/
* 
* MitoGen is free software: 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 3 of the License, or
* (at your option) any later version.
* 
* MitoGen 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 MitoGen. If not, see <http://www.gnu.org/licenses/>.
* 
* Author: David Svoboda and Vladimir Ulman
* 
* Description: 
* An implementation of events that happen in a cell during prophase.
*
***********************************************************************/

#include <sstream>

#include "cell.h"
#include "toolbox/flowfields.h"

//
// look into cell_00_Samplephase.cpp to see full version of the
// template for an atomic cell phase function like this one
//

template <class MV, class PV>
void Cell<MV, PV>::DoProphase(const size_t noFrames)
{
	 REPORT("\n   *****   *****   cell ID=" << ID << ", STARTING Prophase at timePoint=" << 
			  timePoint); 

	// ---------- local working masks ----------
	//local working copy of the cell mask - not needed
	//only nucleus
	i3d::Image3d<MV> maskNucleus;

	maskNucleus.SetResolution(scheduler.sceneRes);
	maskNucleus.SetOffset(scheduler.sceneMasks[timePoint]->GetOffset());
	//but the size of _nucleus_ mask image should contain the whole _cell_
	AllocateAndZeroNewMask(maskNucleus, scmCellBPList, noFrames, cellLookDistance);

	//prepare also working copy of cell nucleus without nucleoli
	DEBUG_REPORT("Rendering nucleus boundary points into mask");
	RenderBPListIntoMask(maskNucleus,(MV)1,
	  scmNucleusBPList,scmNucleusBPCentre,scmNucleusOuterBPNumber);
	// now in the maskNucleus image: 0 means outside, 1 nucleus
	// During Prophase, the nucleoli should dissolve
	DEBUG_REPORT("Rendering finished.");

	i3d::Image3d<float> *distanceMap = NULL;

	// ---------- helper flow fields ----------
	FlowField<float> FF;
	InitFlowField(maskNucleus,FF);

	// ---------- actions a phase needs to do before the frame generating cycle ----------
	//prepare the activity plan to spread the phase duties over the given number of frames

	//the main cycle
	for (size_t T=0; T < noFrames; ++T) {
		REPORT("\n   *****   *****   cell ID=" << ID << ", doing Prophase at timePoint=" << timePoint \
		       << " with sync");

		//
		// internals
		//

		//no change of cell shape here
		
		//just movement of dots:
		//over all chromosomes
		float progress = ((float) T+1.0f) / ((float)noFrames);

		DEBUG_REPORT("Starting " << 100*progress << "% of condensation");
		for (size_t i=0; i < chrCount; ++i) 
		{
			  ChrMoveWithGravity(i,progress*0.65f,maskNucleus,distanceMap,1);
			  ChrMoveWithBrown(i,progress*0.2f,maskNucleus,distanceMap,1);
		}
		DEBUG_REPORT(100*progress << " % of condensation completed");

		//
		// externals
		//

		//reset the current flow field
		FF.x->GetVoxelData()=0.f;
		FF.y->GetVoxelData()=0.f;
		if (FF.z) FF.z->GetVoxelData()=0.f;

		ScmUniversalMovement(FF);


		//
		// a footer common to all phase functions:
		//

		//move the boundary points and draw cell into sceneMasks
		MoveBPListAndCentre(scmCellBPList,scmCellBPCentre,FF);
		MoveBPListAndCentre(scmNucleusBPList,scmNucleusBPCentre,FF);
		ScmRemoveCellFromMask(*scheduler.sceneMasks[timePoint+1]);
		ScmRenderCellIntoMask(*scheduler.sceneMasks[timePoint+1]
#ifdef GTGEN_WITH_NUCLEIMASKS
			,scheduler.sceneNuclei[timePoint+1]
#endif
		);


		//update also the local masks
		//no need to update cell now, it is not used in the cycle

		//nucleous without nucleoli (nucleoli disappeared in Prophase)
		maskNucleus.Clear();
		RenderBPListIntoMask(maskNucleus,(MV)1,
		  scmNucleusBPList,scmNucleusBPCentre,scmNucleusOuterBPNumber);

		if (distanceMap)
		{
			 delete distanceMap; 
			 distanceMap = NULL; // force recomputing distance map
		}

		//update dots in the masks
		ChrMoveByFlow(FF, maskNucleus, distanceMap,(MV)1);
		ChrCentrosomesMoveByFlow(FF, maskNucleus, distanceMap,(MV)1);

		ChrUpdateStats();

		//draw the phantom image
		ChrRenderIntoPhantoms(*scheduler.scenePhantoms[timePoint+1]);
#ifdef GTGEN_WITH_TERRITORIES
		ChrRenderIntoTerritories(*scheduler.sceneTerritories[timePoint+1]);
#endif

		++timePoint;
	}
		
	/*
	 * Note: after Prophase, there is no nucleus. It has disappeared.
	 * Delete its representation as well as representations of both nucleoli.
	 */
	scmNucleusBPList.clear();
	scmNucleusOuterBPNumber=0;

#ifdef ENABLE_NUCLEOLI
	scmNucleoli1BPList.clear();
	scmNucleoli1OuterBPNumber=0;
	scmNucleoli2BPList.clear();
	scmNucleoli2OuterBPNumber=0;
#endif

	//cleaning here if necessary
	
	if (distanceMap)
		 delete distanceMap;
}

//----------------------------------------------------------------------
// explicit instantiations to force explicit build of the functions 
// in this file because otherwise the linker couldn't find them
//----------------------------------------------------------------------
template class Cell<i3d::GRAY8,  i3d::GRAY16>;
template class Cell<i3d::GRAY16, i3d::GRAY16>;
