#ifndef _UNIT_H_
#define _UNIT_H_

#include "allegro.h"
#include "UnitInput.h"
#include "UnitList.h"
#include "UnitTemplate.h"
#include "AddUnitTemplate.h"
#include "gameConstants.h"
#include "MusicSound.h"
#include "Loader.h"
#include "Round.h"
#include <vector>
#include <string>
using namespace std;

//unitHealth should have the status effects and condition (dead/stun etc) of the unit.
//Pass a variable for the amount of stuff the player gets. (make it part of the playerUnit inherited class.)

class UnitList;

struct kbForce {
  kbForce ()
  {dir = itofix (0); mag = itofix (0); duration = 0;affectedByArena = true;};

  kbForce (fixed d, fixed m, int dur)
  {dir = d; mag = m; duration = dur; affectedByArena = true;};

  kbForce (fixed d, fixed m, int dur, bool aba)
  {dir = d; mag = m; duration = dur; affectedByArena = aba;};

  fixed dir;
  fixed mag;
  int duration;
  bool affectedByArena;
};

class Unit {
 public:
  Unit (UnitList *, UnitTemplate *, Unit *, fixed, fixed, fixed, fixed, int = subUnitNone);

  virtual void draw (BITMAP *, MusicSound *, bool);
  virtual void decideAction ();
  void dealDamage ();
  virtual void takeDamage ();
  virtual void endOfRound ();
  virtual void reduceScore (int);

  void alignStyleMove ();

  void storeJuiceForPlayer (fixed);
  void giveJuiceToPlayer (int &);

  vector <AddUnitTemplate *> * getAddedUnits (int);

  void setUnitList (UnitList *);
  void setRound (Round *);
  void setUnitTemplate (UnitTemplate *);
  void addKnockBack (fixed d, fixed m, int dur);
  void addKnockBack (fixed d, fixed m, int dur, bool b);
  void addKnockBack (kbForce * kb);

  bool canAddUnit (vector <AddUnitTemplate *> *);
  virtual void addUnit (vector <AddUnitTemplate *> *, bool, int);

  virtual ~Unit ();

  //commands for the UnitInput to use
  void faceAngle (fixed ang);
  void setFaceAngle (fixed ang);
  void setWalkAngle (fixed ang);
  void walk (bool);
  fixed getWalkAngle ();
  fixed getDrawAngle ();
  bool getWalking ();
  fixed getPosX ();
  fixed getPosY ();
  int getAffiliation ();
  string * getUnitName ();

  //hit detection
  fixed getPicSize ();
  fixed getDrawScale ();
  int shouldCheckToGetHit (Unit *, bool &);
  void getHitKnockback (Unit *, bool);
  void getHitDamage (Unit *);

  bool youAreDead ();
  void killSelf ();
  bool getRemoveThisUnit ();
  int getCharAnim ();

  int getUnitPropertyPlayer ();
  int getUnitPropertyHitbox ();
  int getUnitPropertyStatus ();
  int getUnitPropertyDefense ();

  int getHP ();
  int getMaxHP ();
  void addDamage (int);
  void addGoodStatus (int index, int dur);
  void addBadStatus (int index, int dur);
  void clearGoodStatus (int index);
  void clearBadStatus (int index);
  virtual void changeGoodStatusMax (int index, int val);
  virtual void changeBadStatusMax (int index, int val);
  vector <int> * getGoodStatus ();
  vector <int> * getBadStatus ();

  void changeAnim (int);
  BITMAP * getPic (bool);
  int getAnimCurrent ();
  bool getAnimFinished ();
  fixed getFrameSize ();

 protected:

  string * unitType;
  vector <AddUnitTemplate *> * addedUnits;

  UnitInput * uin;
  UnitList * units;
  UnitTemplate * ut;

  //unit's properties (ethereal, bounces, outofbounds, etc)
  int affiliation;
  int unitPropertyHitbox;
  int unitPropertyDefense;
  int unitPropertyStatus;
  int unitPropertyPlayer;
  int subUnitType; //for making variants of the same enemy
  int timeToLive;
  int charAnim;
  bool removeThisUnit;

  int maxHP;
  int hitPoints;
  int costOfAttack;
  vector <int> * goodStatus;
  vector <int> * badStatus;

  //movement
  fixed walkAngle;
  bool walking;
  fixed walkMag;
  fixed kbVelX;
  fixed kbVelY;
  vector <kbForce> * kbForces;
  Round * rnd;

  //attack interrupts
  int cantAttack1;
  int cantAttack2;
  int cantAttack4;
  int cantMove;

  //drawing
  fixed posX, posY;
  fixed drawAngle;
  fixed drawScale;
  bool animJustAttacked;
  int animAttackNum;
  int soundToPlay;
  bool noMoreSfx;

  int animFrame, animFrameMax, animCurrent;
  bool animationFinished;
  int moveForwardCounter;

  //owning unit and alignment
  Unit * ownUnit;
  int alignStyle;
  fixed alignDist;
  fixed alignAngleMin;
  fixed alignAngleMax;

  //damage and knockback dealt
  kbForce * hitKB;
  int damageDealt;
  int damageTakenThisFrame;
  int outOfBoundFrames;
  vector <int> * goodStatusDamage;
  vector <int> * badStatusDamage;

  //juice
  int juiceReward;
  int juiceForPlayer;
  fixed percentJuice;
};

#endif
