// Copyright (c) 2023 Dominic Masters
// 
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT

#include "SolidController2D.hpp"

using namespace Dawn;

SolidController2D::SolidController2D(std::weak_ptr<SceneItem> item) : SceneItemComponent(item) {
}

std::vector<std::shared_ptr<SceneItemComponent>> SolidController2D::getDependencies() {
  return {
    (this->collider = item.lock()->getComponent<Collider2D>())
  };
}

bool_t SolidController2D::getCollidingResult(
  glm::vec2 movement,
  std::shared_ptr<Collider2D> movingObject,
  glm::vec2 &normal,
  float_t &entryTime,
  float_t &exitTime,
  glm::vec2 &entryPoint,
  glm::vec2 &exitPoint
) {
  assertNotNull(this->collider, "SolidController2D::getCollidingResult: Collider cannot be null");
  assertNotNull(movingObject, "SolidController2D::getCollidingResult: Moving object cannot be null");
  if(movement.x == 0 && movement.y == 0) return false;

  auto myPos = physics3Dto2D(movingObject->item.lock()->getWorldPosition());

  // Check what the moving object is
  switch(movingObject->getColliderType()) {
    case COLLIDER2D_TYPE_BOX: {
      auto box1 = std::static_pointer_cast<BoxCollider>(movingObject);
      assertNotNull(box1, "SolidController2D::getCollidingResult: Moving object is not a BoxCollider");

      // Box VS (this)?
      switch(this->collider->getColliderType()) {
        case COLLIDER2D_TYPE_BOX: {
          auto box2 = std::static_pointer_cast<BoxCollider>(this->collider);
          assertNotNull(box2, "SolidController2D::getCollidingResult: Collider is not a BoxCollider");
          auto otherPos = physics3Dto2D(box2->item.lock()->getWorldPosition());

          return boxCheckCollision(
            myPos, box1->min, box1->max,
            otherPos, box2->min, box2->max,
            movement,
            normal, entryTime, exitTime, entryPoint, exitPoint
          );
        }
        
        default: {
          assertUnreachable("SolidController2D::getCollidingResult: Collider type not implemented");
        }
      }
      break;
    }

    default: {
      assertUnreachable("SolidController2D::getCollidingResult: Moving object type not implemented");
    }
  }
  
  assertUnreachable("SolidController2D::getCollidingResult: Should never reach this point");
  return false;
}