#ifndef PLAYERCHARACTERNODE_H
#define PLAYERCHARACTERNODE_H

#include "cameranode.h"
#include "SparrowInput/input.h"
#include <LinearMath/btVector3.h>

class btRigidBody;
class btDefaultMotionState;
class PointLight;
class LightNode;

class FirstPersonCamera : public BasicCamera
{
private:
    // camera position
    glm::vec3 m_eye;
    glm::vec3 m_direction;
    glm::vec3 m_upVector;

    void computeView();

public:
    FirstPersonCamera(float myFov = 70.f, float myNear = 0.1f, float myFar = 1000.f);

    void move(const glm::vec3 &translation);
    void rotate(float dx, float dy);
    void moveTo(const glm::vec3 &targetPos);
    void lookAt(const glm::vec3 &targetPos);

    void setUpVector(const glm::vec3 &up);
    const glm::vec3& getEyePosition() { return m_eye; }
    const glm::vec3& getDirection() { return m_direction; }
};

class PlayerCharacterNode : public CameraNode
{
    btRigidBody* m_rigidBody;
    FirstPersonCamera m_fpsCamera;

    bool m_jumping;
    bool m_noclipMode;
    btVector3 m_noclip_pos;

    PointLight* m_playerLight;
    LightNode* m_playerLightNode;

    std::vector<int> m_inputActions;

    float m_last_displacement;

    enum PlayerAction {FORWARD, BACKWARD, STRAFE_LEFT, STRAFE_RIGHT, JUMP, RUN, TOGGLE_NOCLIP};

public:
    PlayerCharacterNode(bool noClip = true);
    ~PlayerCharacterNode();

    void setInputs(int forward, int backward, int strafe_left, int strafe_right, int jump = NO_ACTION, int run= NO_ACTION, int toggleNoClip = NO_ACTION);

    void setPosition(float x, float y, float z);

    glm::vec3 getEyePosition() { return m_fpsCamera.getEyePosition(); }
    glm::vec3 getDirection() { return m_fpsCamera.getDirection(); }

    virtual void update();

    void toggleNoClip();

    btRigidBody* getRigidbody() { return m_rigidBody; }

    virtual Camera *getCamera() { return &m_fpsCamera; }

    virtual void setSceneTree(SceneTree* tree);
};

#endif // PLAYERCHARACTERNODE_H
