#include "object.h"
#include "mymath.h"
#include "globals.h"

#define MAX_PEOPLE_PER_CONTROL    18



#define TYPE_AI_NORMAL     0
#define TYPE_AI_HUNTER     1
#define TYPE_AI_BLOCK      2
#define TYPE_AI_COWARD     3


#define PERSON_GUARD            0
#define PERSON_GUARD_SNOWBALL   1
#define PERSON_AUTOMATED_GUARD  2
#define PERSON_SANTA            3
#define PERSON_ELF              4
#define PERSON_ELF_SHIELD       5
#define PERSON_ELF_SIGN         6
#define PERSON_ELF_TORCH        7
#define PERSON_ELF_SNOWBALL     8
#define PERSON_GRINCH           9
#define PERSON_CAMERA           10
#define PERSON_SANTA            11


#ifndef PERSON_H_INCLUDED
#define PERSON_H_INCLUDED


class Person : public Object {
  protected:
    Vec2D target, dir, off_force, target_sweep;

    float last_x, last_y;
    float speed;
    float new_angle;
    float inmovile_time;
    std::vector<AnimatedSprite> sprites;
    int actual_animation;
    bool mine, over, selected;
    std::string name;
    float life, max_life;
    Person *target_p;
    float attack_range;
    float attack_wait;
    float damage_reduction;
    float attack_speed;
    float hunt_range;
    int type_ai;
    float delay_ai;
    Person *attacker;
    bool can_guard, grinch;
    bool robot;

    float damage;

    float morale;

    bool guard_mode, morale_effect, santa;

    int projectile_attack;

    float flashed;
    float morale_influence;
    float morale_modifier;

    bool smoked;

    int type;
    bool gas_protection;

    float hoho_delay;

    CacheBitmap *portrait;
    bool has_torch;
  public:
    Person() {Reset(); target=Vec2D(-1, -1); name = "";speed=0; sprites.clear(); actual_animation=0;
    speed=2;mine=false;selected=false;life=max_life=50;target_p=NULL; attack_range = 32;damage_reduction=1.0;
    attack_speed=60;hunt_range=100;type_ai=0;attacker=NULL;projectile_attack=-1;target_sweep=Vec2D(-1,-1);damage=5;
    guard_mode=false;has_torch=false;flashed=0;can_guard=false; morale=50;morale_influence=0.5;morale_modifier=1.0;
    morale_effect=false; grinch=false;smoked=false;gas_protection=false;robot=false;type=0;santa=false;hoho_delay=160;}

    void SetName(std::string s) {name=s;}
    std::string GetName() {return name;}

    void SetSanta(bool b) {santa=b;}
    bool GetSanta() {return santa;}

    virtual void LoadGraphics(std::string filename);

    void SetType(int v) {type=v;}
    int GetType() {return type;}

    void UpdateGeneral();

    void SetRobot(bool v) {robot=v;}
    bool IsRobot() {return robot;}

    void SetMaxLife(float v) {max_life=v;life=v;}

    void SetGasProtection(bool v) {gas_protection=v;}
    bool HasGasProtection() {return gas_protection;}

    void SetGrinch(bool v) {grinch=v;}
    bool IsGrinch() {return grinch;}

    void AffectMorale(float v) {
      morale += (v*morale_modifier);
    }

    void SetMoraleInfluence(float v) {morale_influence = v;}
    void SetMoraleModifier(float v) {morale_modifier = v;}
    void SetMorale(float v) {morale = v;}

    void SetAttackSpeed(float v) {attack_speed=v;}

    void SetCanGuard(bool v) {can_guard=v;}

    void SetSpeed(float v){speed=v;}

    void AddTorch(){has_torch=true;}

    void SetTarget(float tx, float ty) {
      target.x = tx; target.y = ty;
    }
    void SetProjectileAttack(int v) {
      projectile_attack = v;
    }

    void InfluenceMorale();

    void Flash(float v) {
      flashed = v;
      target_p = NULL;
      morale -= 20;
    }

    void OrderStop() {
      target.x=-1;
      target_sweep.x=-1;
      guard_mode=false;
      target_p=NULL;
    }

    float GetCanGuard() {return can_guard;}

    void OrderGuard() {
      if (!can_guard) return;
      sprites[4].frame=0;
      guard_mode=true;
      target.x=-1;target_sweep.x=-1;
      target_p=NULL;
    }
    void SetDamage(float v) {damage = v;}
    void SetAttackRange(float v) {attack_range=v;}
    void SetHuntingRange(float v) {hunt_range=v;}
    void UpdateAngle();
    void UpdateOver();
    void UpdateWalk();
    void UpdateSweep();
    void UpdateAttack();
    void DrawGeneral();
    void Separate();
    bool IsInRange(float, float, float);
    void SetMine(bool b) {mine=b;}
    void Select() {selected = true;}
    void Deselect() {selected = false;}
    bool IsMine() {return mine;}
    bool IsSelected() {return selected;}
    void UpdateAI();
    void TargetAttack(Person *p);
    void Attack(Person *p);
    void Hit(float v);
    bool IsUnconscious() {return (life <= 0);}
    void SearchForNextEnemy();

    void DrawLight();

    void TargetWalk(float tx, float ty) {
      target_p = NULL;
      SetTarget(tx, ty);
      target_sweep.x = -1;
      guard_mode=false;
    }
    void TargetSweep(float tx, float ty) {
      target_p = NULL;
      target.x=-1;
      target_sweep.x=tx; target_sweep.y=ty;
      guard_mode=false;
    }

    float GetLifePercent() {return (life/max_life);}

    bool InSameSide(Person *p) {
      if ((mine) && (p->IsMine())) return true;
      if ((!mine) && (!p->IsMine())) return true;
      return false;
    }

    CacheBitmap *GetPortrait() {return portrait;}

    void DeleteGeneral() {
      for (std::vector<AnimatedSprite>::iterator it=sprites.begin(); it!=sprites.end(); it+=1) (*it).Clear();
      sprites.clear();
    }

    void Smoking() {smoked=true;}

    ~Person() {
      DeleteGeneral();
    }
};


extern std::deque<Person *> persons;
extern Person *ActualOver;

extern std::deque<Person *> actual_selection;

void DeselectAllPeople();
bool AnyPeopleSelected();
void GetCurrentSelection();


#endif
