#include "GResource.h"
#include "Ansprite.h"

#ifndef VOBJECT_H_INCLUDED
#define VOBJECT_H_INCLUDED


enum AnimationType {
  MOVE_X,
  MOVE_Y,
  SIZE_W,
  SIZE_H,
  TINT,
  OPACITY,
  ROTATE
};


class Animation {
  public:
    enum AnimationType type;
    float target_s;
    GCOLOR target_c;
    float duration, life;

    Animation(enum AnimationType t, float d) {type=t; duration=d; life=d;}
};


class VObject {
  protected:
    GBitmap *actual_bit;
    float l_x, l_y, x, y, z, w, h, c_x, c_y, or_x, or_y, or_w, or_h, angle, or_angle, l_angle;
    GCOLOR tint, or_tint;

    AnimatedSprite *an_sprite;

    bool motion_blur;

    float shadow;
    bool decay;
    float life;

    std::deque<Animation *> animations;

    VObject *next_z;
    VObject *prev_z;
  public:
    VObject(){Reset();}

    // Constructor with defined position and size
    VObject(GBitmap *bt, float tx, float ty, float tw, float th, float an, GCOLOR c=GCOLOR_WHITE) {
      Reset();
      actual_bit = bt;
      x=tx; y=ty; w=tw; h=th;

      angle = an;
      tint = c;
      SetOriginals();
    }

    // Constructor with defined position and scaled size
    VObject(GBitmap *bt, float tx, float ty, float sc=1.0, float an=0, GCOLOR c=GCOLOR_WHITE) {
      Reset();
      actual_bit = bt;
      x=tx; y=ty;

      w = bt->Width(); h = bt->Height();
      w *= sc; h *= sc;

      angle = an;
      tint = c;
      SetOriginals();
    }

    // Constructor which uses an animated sprite with defined position and size
    VObject(AnimatedSprite *bt, float tx, float ty, float tw, float th, float an, GCOLOR c=GCOLOR_WHITE) {
      Reset();
      an_sprite = bt;
      actual_bit = an_sprite->GetActualBit();
      x=tx; y=ty; w=tw; h=th;

      angle = an;
      tint = c;
      SetOriginals();
    }

    // Constructor which uses an animated sprite with defined position and scaled size
    VObject(AnimatedSprite *bt, float tx, float ty, float sc=1.0, float an=0, GCOLOR c=GCOLOR_WHITE) {
      Reset();
      an_sprite = bt;
      actual_bit = an_sprite->GetActualBit();
      x=tx; y=ty;

      w = bt->Width(); h = bt->Height();
      w *= sc; h *= sc;

      angle = an;
      tint = c;
      SetOriginals();
    }


    void SetOriginals() {
      or_x=x; or_y=y; or_w=w; or_h=h;
      or_tint = tint;
      or_angle = angle;
    }

    void Reset() {
      x=y=w=h=or_x=or_y=or_w=or_h=angle=or_angle=z=0;
      shadow = 0;
      decay = false;
      life = 1;
      animations.clear();
      actual_bit=NULL;
      an_sprite=NULL;
      c_x=-1; c_y=-1;
      motion_blur = false;
    }

    void Update();
    void Draw();

    void SetLife(float lf) {
      life = lf;
      decay = true;
    }

    float GetLife() {
      return life;
    }

    bool Dead() {return (life <= 0);}

    void AnimateOverride(Animation *an) {
      animations.clear();
      Animate(an);
    }

    void Animate(Animation *an) {
      animations.push_back(an);
    }

    void UpdateAnimation(Animation *an);

    void SetToOriginal() {
      x=or_x; y=or_y; w=or_w; h=or_h;
      tint = or_tint;
      angle = or_angle;
    }

    void ClearAnimationType(enum AnimationType);

    void AnimateMoveTo(float, float, float);
    void AnimateMoveX(float, float);
    void AnimateMoveY(float, float);

    void AnimateScale(float, float);
    void AnimateSizeW(float, float);
    void AnimateSizeH(float, float);

    void SetCenter(float vx, float vy) {c_x=vx; c_y=vy;}

    ~VObject();


    void SetMotionBlur(bool v) {motion_blur = v;}
    bool GetMotionBlur() {return motion_blur;}

    void AnimateTint(float dr, float dg, float db, float da, float d);

    void AnimateRotate(float dr, float d);


    AnimatedSprite *GetAnsprite() {return an_sprite;}

    void SetActualAnimation(std::string nm) {if (an_sprite != NULL) an_sprite->SetActualAnimation(nm);}
    bool Finished() {
      if (an_sprite != NULL) return an_sprite->Finished();
      return false;
    }

    void SetAtEnd() {
      if (an_sprite != NULL) an_sprite->SetAtEnd();
    }

    void SetAtFrame(float v) {
      if (an_sprite != NULL) an_sprite->SetAtFrame(v);
    }

    void SetAtFrameP(float v) {
      if (an_sprite != NULL) an_sprite->SetAtFrameP(v);
    }

    void SetAngle(float v) {
      angle = v;
    }

    void SetX(float v) {x = v;}
    float GetX() {return x;}

    void SetY(float v) {y = v;}
    float GetY() {return y;}

    void SetZ(float v) {z = v;}
    float GetZ() {return z;}

    void set_z_prev(VObject *ob) {prev_z = ob;}
    void set_z_next(VObject *ob) {next_z = ob;}

    void SetShadow(float v) {
      shadow = v;
    }

    void SetTint(GCOLOR c) {
      tint = c;
    }

    void SetActualAnimationSpeed(float v) {
      if (an_sprite != NULL) an_sprite->SetActualAnimationSpeed(v);
    }

    VObject *get_z_prev() {return prev_z;}
    VObject *get_z_next() {return next_z;}
};

VObject *AddVObject(VObject *v);
void DeleteVObject(VObject *v);

void UpdateVisualObjects();
void DrawVisualObjects();


extern std::deque<VObject *> VisualObjects;

void ClearVisualObjects();


#endif
