#include "../include/config.h"
#include "../include/AIStats.h"
#include "../include/GameObserver.h"
#include "../include/Player.h"
#include "../include/MTGCardInstance.h"

bool compare_aistats(AIStat * first, AIStat * second){
  float damage1 = first->value / first->occurences;
  float damage2 = second->value/ second->occurences;
  return (damage1 > damage2);
}

AIStats::AIStats(Player * _player, char * _filename){
  filename = _filename;
  load(_filename);
  player = _player;
}

AIStats::~AIStats(){
  list<AIStat *>::iterator it;
  for ( it=stats.begin() ; it != stats.end(); it++ ){
    AIStat * stat = *it;
    delete stat;
  }
}

void AIStats::updateStatsCard(MTGCardInstance * cardInstance, Damage * damage, float multiplier){
  MTGCard * card = cardInstance->model;
  AIStat * stat = find(card);
  if (!stat){
    stat = NEW AIStat(card->getMTGId(),0,1,0);
    stats.push_back(stat);
  }
  if (damage->target == player){
    stat->value+= multiplier * STATS_PLAYER_MULTIPLIER * damage->damage;
  }else if (damage->target->type_as_damageable == DAMAGEABLE_MTGCARDINSTANCE){
    MTGCardInstance * target = (MTGCardInstance *)damage->target;
    if (target->controller() == player && !target->isInPlay()){
      //One of my creatures got lethal damage...
      stat->value+= multiplier * STATS_CREATURE_MULTIPLIER * damage->damage;
    }
  }
}

void AIStats::updateStats(){
  GameObserver * game = GameObserver::GetInstance();
  ActionStack * as = game->mLayers->stackLayer();
  Damage * damage = ((Damage * )as->getNext(NULL,ACTION_DAMAGE, RESOLVED_OK));
  MTGGameZone * opponentZone = player->opponent()->game->inPlay;
  while(damage){
    MTGCardInstance * card = damage->source;
    updateStatsCard(card,damage);

    //Auras on damage source can be the cause
    for (int i=0;  i < opponentZone->nb_cards; i++){
      MTGCardInstance * aura = opponentZone->cards[i];
      if (aura->target == card){
	updateStatsCard(aura,damage, STATS_AURA_MULTIPLIER);
      }
    }
    damage = ((Damage * )as->getNext(damage,ACTION_DAMAGE, RESOLVED_OK));
  }
  stats.sort(compare_aistats);
}

bool AIStats::isInTop(MTGCardInstance * card, unsigned int max, bool tooSmallCountsForTrue ){
  if (stats.size()<max) return tooSmallCountsForTrue;
  unsigned int n = 0;
  MTGCard * source = card->model;
  int id = source->getMTGId();
  list<AIStat *>::iterator it;
  for ( it=stats.begin() ; it != stats.end(); it++ ){
    if (n >= max) return false;
    AIStat * stat = *it;
    if (stat->source == id){
      if (stat->value>=0) return true;
      return false;
    }
    n++;
  }
  return false;
}

AIStat * AIStats::find(MTGCard * source){
  int id = source->getMTGId();
  list<AIStat *>::iterator it;
  for ( it=stats.begin() ; it != stats.end(); it++ ){
    AIStat * stat = *it;
    if (stat->source == id) return stat;
  }
  return NULL;
}

void AIStats::load(char * filename){
  std::ifstream file(filename);
  std::string s;

  if(file){
    while(std::getline(file,s)){
      int cardid = atoi(s.c_str());
      std::getline(file,s);
      int value = atoi(s.c_str());
      std::getline(file,s);
      int direct = atoi(s.c_str());
      AIStat * stat = NEW AIStat(cardid,value,1,direct);
      stats.push_back(stat);
    }
    file.close();
  }else{
    //TODO Error management
  }
}
void AIStats::save(){
  std::ofstream file(filename.c_str());
  char writer[128];
  if (file){
    list<AIStat *>::iterator it;
    for ( it=stats.begin() ; it != stats.end(); it++ ){
      AIStat * stat = *it;
      if (stat->value > 0){
	sprintf(writer,"%i\n%i\n%i\n", stat->source,stat->value/2,stat->direct);
	file<<writer;
      }
    }
    file.close();
  }

}
