#include "Kicker.hpp"
#include "Island.hpp"
#include "House.hpp"
#include "Tree.hpp"
#include "Enemy.hpp"
#include "Hero.hpp"
#include "Sky.hpp"

namespace Play {
  class Logic : public FirstPerson::Logic {
    const Sky sky;
    Graphics& renderObjects() override {
      sky.render();
      return FirstPerson::Logic::renderObjects();
    }
  public:
    Logic() : FirstPerson::Logic(
      "Play v1.21",
      13.0,
      new Hero()
    ) {
      static const unsigned int n = static_cast<const unsigned int>(R);
      static Vector v;
      for (
        unsigned int i = 0;
        i < n;
        i++
      ) {
        Object* object = new House(
          i + 0.5,
          0.5 + 0.25 * Math::rand()
        );
        v.set(
          R * 2 / 5,
          object->getRy()
        ).rotateY(Math::PImul2 *  i / n);
        object->setPosition(v).setDirection(v).setActive();
        Enemy::nests.push_back(object);
        {
          Object* object = new Island();
          v.set(
            R * (
              3 + (i % 2 ? 0 : 1)
            ) / 5,
            n - object->getRy() * 2 * (
              1 + sin(Math::PI * 4 * i / n)
            )
          ).rotateY(
            Math::PImul2 * (i - 1.0) / n
          );
          object->setPosition(v).setDirection(v).setActive();
          Enemy::nests.push_back(object);
        }
        {
          Object* object = new Tree(
            (n * 2 - i) / 3
          );
          object->setPosition(
            v.set(
              R * (
                3.5 + (i % 2 ? 0.5 : 0)
              ) / 5,
              object->getRy()
            ).rotateY(
              Math::PImul2 * (i + 4) / n
            )
          );
          object->setDirection(
            v.rotateY(
              Math::PImul2 * Math::rand()
            )
          ).setActive();
        }
      }
      {
        Object* object = new Kicker(1.25);
        v.zero().y = object->getRy();
        object->setPosition(v).setActive();
      }
      for (
        unsigned int i = 0;
        i < 5;
        i++
      ) {
        if (i < 3) {
          new WhiteEnemy();
        } else {
          new CyanEnemy();
        }
      }
    }
  };
}

Logic* Logic::create() {
  return new Play::Logic();
}
