#include "Element_Medicine.h"
#include "Element_Tumor.h"
namespace MFM {


  /*******************************
   * catch medicine *
   *******************************/
  template<class CC>
  bool Element_Aura<CC>::CatchMedicine(EventWindow<CC>& window) const{
      MDist<R>& md = MDist<R>::get();
      Random & random = window.GetRandom();
      WindowScanner<CC> scanner(window);
      const T& me = window.GetCenterAtom();
      SPoint medRel;
      SPoint empRel;
      u32 medCount = 0;
      u32 empCount = 0;

      s8 xMed=0;
      s8 yMed=0;
      s8 xEmp=0;
      s8 yEmp=0;

      for (u32 idx = md.GetFirstIndex(1); idx <= md.GetLastIndex(R); ++idx)
      {
        const SPoint rel = md.GetPoint(idx);
        if (!window.IsLiveSite(rel))
        {
          continue;
        }
        T other = window.GetRelativeAtom(rel);
        u32 type = other.GetType();
        if(type == Element_Medicine<CC>::THE_INSTANCE.GetType())
        {
	  u16 ydns = Element_Medicine<CC>::THE_INSTANCE.GetAid(other);
	  u16 mdns = GetDense(me);
          if(mdns>ydns){
	    ++medCount;
	    xMed=rel.GetX();
	    yMed=rel.GetY();
	    medRel = rel;
	  }
	  LOG.Debug("==med(%d,%d),dns(%d,%d)",rel.GetX(),rel.GetY(),mdns,ydns);
        }
	if(type == Element_Empty<CC>::THE_INSTANCE.GetType())
        {
	  xEmp=rel.GetX();
	  yEmp=rel.GetY();
	  if(((xEmp>=-1)&&(xEmp<=1))&&((yEmp>=-1)&&(yEmp<=1))){
	    if(random.OneIn(++empCount)){
	      empRel = rel;
	    }
	  }
	  LOG.Debug("==find emp(%d,%d)",rel.GetX(),rel.GetY());
        }
      }
      if(medCount>0){
	if(empCount>0){
	  if (random.OneIn(1)){
	    window.SwapAtoms(SPoint(0,0),medRel);
	    return true;
	  }
	}else{
	  T otherMed=window.GetRelativeAtom(medRel);
	  Element_Medicine<CC>::THE_INSTANCE.SetXLoc(otherMed,-1*xMed);
	  Element_Medicine<CC>::THE_INSTANCE.SetYLoc(otherMed,-1*yMed);
	}
      }
      return false;
    }
  /*******************************
   * check neighbor aura density *
   *******************************/
  template<class CC>
  void Element_Aura<CC>::ChkDen(EventWindow<CC>& window) const{
      MDist<R>& md = MDist<R>::get();
      T me = window.GetCenterAtom();
      WindowScanner<CC> scanner(window);
      Random & random = window.GetRandom();

      u8 nbrCount = 0;
      u8 tmrCount = 0;
      u16 dns = 0;
      //u16 d0 = 35; 20141117 put to tumor-parameter
      u16 d0 = GetLife(me)*5;
      for (u32 idx = md.GetFirstIndex(1); idx <= md.GetLastIndex(R); ++idx)
      {
        const SPoint rel = md.GetPoint(idx);
        if (!window.IsLiveSite(rel))
        {
          continue;
        }
        T other = window.GetRelativeAtom(rel);
        u32 type = other.GetType();
	if(type == Element_Tumor<CC>::THE_INSTANCE.GetType())
        {
          ++tmrCount;
	  LOG.Debug("==find tumor(%d,%d)",rel.GetX(),rel.GetY());
	}
        if(type == Element_Aura<CC>::THE_INSTANCE.GetType())
        {
          ++nbrCount;
	  LOG.Debug("==find aura(%d,%d)",rel.GetX(),rel.GetY());
	}
      }
      dns = 0.1*tmrCount +nbrCount+2;
      if (d0 == 0){
	//signals never die!20141117 put to tumor-parameter
	SetDense(me,dns);
	window.SetCenterAtom(me);
      }
      else{
	if(dns<=2){
	  if (random.OneIn(d0-dns)){
	    window.SetCenterAtom(Element_Empty<CC>::THE_INSTANCE.GetDefaultAtom());
	  }else{
	    SetDense(me,dns);
	    window.SetCenterAtom(me);
	  }
	}else{
	  if (random.OneIn(abs(3*d0-(dns)))){
	    window.SetCenterAtom(Element_Empty<CC>::THE_INSTANCE.GetDefaultAtom());
	  }else{
	    SetDense(me,dns+1);
	    window.SetCenterAtom(me);
	  }
	}
      }
    }

    /*******************************
     * main behaviors
     *******************************/
  template<class CC>
  void Element_Aura<CC>::Behavior(EventWindow<CC>& window) const
    {
      //Random & random = window.GetRandom();
      const T us = window.GetCenterAtom();
      T copyUs = window.GetCenterAtom();
      WindowScanner<CC> scanner(window);
      bool canCatch = false;

      this->ChkDen(window);

    /*if(scanner.CountAtomsOfType(Element_Aura<CC>::THE_INSTANCE.GetType(),R)<=2){
	LOG.Debug("===>less than 1 aura in event-window");
	if (random.OneIn(80)){
	  window.SetCenterAtom(Element_Empty<CC>::THE_INSTANCE.GetDefaultAtom());
	}
      }
      else{
	if(scanner.CountAtomsOfType(Element_Aura<CC>::THE_INSTANCE.GetType(),R)>=3){
	  if (random.OneIn(20)){
	    window.SetCenterAtom(Element_Empty<CC>::THE_INSTANCE.GetDefaultAtom());
	  }
	}
      }*/
      if(scanner.CountAtomsOfType(Element_Medicine<CC>::THE_INSTANCE.GetType(),R)>0){
	LOG.Debug("med find");
	if(canCatch){
	  if(this->CatchMedicine(window)){
	  }
	}
      }else{
	this->Diffuse(window);
      }
      //this->Diffuse(window);
    }
}
