/*
 * CMaze.h
 *
 *  Created on: 26 Oct 2023
 *      Author: max.petrak
 */

#ifndef SOURCE_CMAZE_H_
#define SOURCE_CMAZE_H_

#include "GUISubject.h"
#include "GUIAnimatable.h"
#include "GUIPoint.h"
#include "GUIObject.h"

#include "GameState_t.h"

class CHardware;
class CLevel;
class CGUIRect;

class CGameObserver
{
public:
    CGameObserver(){}
    virtual ~CGameObserver(){}

    virtual void OnGameStateChange(GameState_t eGameState){}
};

class CGame: public CGUIAnimatable, public CGUISubject
{
public:

    CGame(CHardware* pkHardware);
    ~CGame();

    // basically the game loop
    void DoAnimate(const eC_Value& vTimes);
    // let the ball roll
    void Start();
    // stop the ball
    void Stop();

    void SetLevel(CLevel* kLevel);

    void SetSampleRate(eC_Int iSampleRate);
    eC_Int GetSampleRate();

    void SetField(eC_Value vX1, eC_Value vY1, eC_Value vX2, eC_Value vY2);
    CGUIRect& GetField();

    void Reset();
    void SetObserver(CGameObserver* pkObserver);
    GameState_t GetGameState();
    void OpenNewLevel(ObjectHandle_t eDialogID);

private:
    eC_Bool CheckCollisionBallRect(CGUIRect kBall, CGUIRect kRect);

    // returns the closest point on the rect
    CGUIPoint ClosestPointToPointOnRect(CGUIRect kRect, CGUIPoint kPoint);

    // returns the distance between two points
    eC_Value Distance(CGUIPoint kPoint1, CGUIPoint kPoint2);

    eC_Value Clamp(eC_Value vValue, eC_Value vMin, eC_Value vMax);

    CGUIPoint ClampPoint(CGUIPoint kPoint, CGUIPoint kMin, CGUIPoint kMax);

    CGUIPoint PointPlusPoint(CGUIPoint kPoint1, CGUIPoint kPoint2);

    CGUIPoint PointMinusPoint(CGUIPoint kPoint1, CGUIPoint kPoint2);

    CGUIPoint PointPlusValue(CGUIPoint kPoint, eC_Value vValue);

    CGUIPoint PointTimesValue(CGUIPoint kPoint, eC_Value vValue);

    CGUIPoint NegatePoint(CGUIPoint kPoint);

    eC_Value DotProduct(CGUIPoint kPoint1, CGUIPoint kPoint2);

    CGUIPoint NormalizeVector(CGUIPoint kPoint);

    eC_Bool ValuesClose(eC_Value vValue1, eC_Value vValue2, eC_Value vLeeway);

    void ChangeGameState(GameState_t eGameState);

private:
    CGUIPoint m_kBallPos;
    CGUIPoint m_kBallVelocity;
    eC_Value m_vBallSize;

    CGUIObject* m_pkGUIBall;
    CLevel* m_pkLevel;

    CGUIRect* m_pkField;
    CHardware* m_pkHardware;

    // rate in ms in which the game loop runs
    eC_Int m_iSampleRate;

    eC_Value m_vSmallestMovement;

    CGameObserver* m_pkObserver;

    GameState_t m_eGameState;
};

#endif /* SOURCE_CMAZE_H_ */
