// Geom. Objekte: Statische Member: drawAll (Version mit Set, Z-Wert und Nummer)
// Implementierung der abstrakten Basisklasse "GraObj"
//
// Klaus Kusche, 2020

#include "graobj.h"

#include "sdlinterf.h"

// Implementierung der Vergleichsfunktion
bool GraObjCompare::operator()(const GraObj *a, const GraObj *b) const
{
  // kleinerer Z-Wert ==> Objekt ist kleiner
  // ==> Objekt ist weiter vorne in sObjects
  // ==> Objekt wird von drawAll früher gezeichnet
  // ==> Objekt ist optisch weiter hinten
  //     (danach gezeichnete Objekte werden drübergezeichnet)
  if (a->mZ < b->mZ) return true;
  if (a->mZ > b->mZ) return false;
  // wenn wir hierher kommen, ist a->mZ == b->mZ
  // ein Set erlaubt aber keine sortierordnungsmäßig gleichen Werte
  // daher sortieren wir bei gleichem Z-Wert nach der Objekt-Nummer
  // (ältere Objekte im Hintergrund, neuere größer, d.h. im Vordergrund)
  // die fortlaufende Nummer sollte immer eindeutig sein
  return (a->mNr < b->mNr);
}

// Speicher für die statischen Member anlegen
// ein Set wird automatisch auf "leer" initialisiert
graPtrSet GraObj::sObjects;
int GraObj::sNextNum = 1;

void GraObj::setPos(int x, int y)
{
  undraw();
  mX = x;
  mY = y;
  draw();
}

void GraObj::move(int dx, int dy)
{
  undraw();
  mX += dx;
  mY += dy;
  draw();
}

void GraObj::setSize(int w, int h)
{
  undraw();
  mW = w;
  mH = h;
  draw();
}

void GraObj::scale(int percentX, int percentY)
{
  undraw();
  mW = (mW * percentX) / 100;
  mH = (mH * percentY) / 100;
  draw();
}
  
bool GraObj::fly(bool bounce)
{
  bool ret = true;
  if (((mSX > 0) && (mX >= SDL_X_SIZE - mSX - mW)) ||
      ((mSX < 0) && (mX < -mSX + mW))) {
    if (bounce) {
      mSX = -mSX;
      ret = false;
    }
    else {
      return false;
    }
  }
  if (((mSY > 0) && (mY >= SDL_Y_SIZE - mSY - mH)) ||
      ((mSY < 0) && (mY < -mSY + mH))) {
    if (bounce) {
      mSY = -mSY;
      ret = false;
    }
    else {
      return false;
    }
  }

  move(mSX, mSY);
  return ret;
}

// Zeichne alle Objekte neu
void GraObj::drawAll()
{
  // Seit C++ 11: Die for-:-Schleife belegt die Variable vor dem :
  // der Reihe nach mit allen Elementen im Container nach dem :
  // Da set-Container automatisch sortiert sind,
  // durchläuft das unsere Objekte in aufsteigender Z-Reihenfolge
  for (GraObj *p : sObjects) {
    p->draw();
  }
  // Alte Varianten mit Iterator:
  // Vor C++11: i ist vom Typ "Iterator über unser Set"
  //for (graPtrSet::iterator i = sObjects.begin(); i != sObjects.end(); ++i) {
  // Seit C++11: auto..."gib der Variable den Typ, den der Init-Wert hat"
  //for (auto i = sObjects.begin(); i != sObjects.end(); ++i) {
    // i verhält sich wie ein Pointer auf das aktuelle Element im Set
    // *i ist daher das aktuelle Element im Set, nämlich ein GraObj-Pointer
    // (*i)->draw() ruft für das GraObj, auf den dieser Pointer zeigt, draw auf
    //(*i)->draw();
  //} 
}
