#ifndef SEASONI_H
#define SEASONI_H
#include "pixelGameEngine.h"
#include "splash.h"
#include "soundwaveEngine.h"
#include "defines.h"
#include "flags.h"

using namespace olc;

#define 됐어

class Map;
enum class ItemName;
class Object;
enum class ActionType;
class Entity;
class Effect;
class Cutscene;
class TILE;
namespace Battle{
    class Move;
}

class SeasonI:public PixelGameEngine{
    public:
    SeasonI(){sAppName="Season I: Winters of Loneliness";}
    bool OnUserCreate()override;
    void SetupMoveList(); 됐어
    void SetupItemList(); 됐어
    void SetupPartyMemberStats(); 됐어
	void SetupAnimations(); 됐어
	void SetupObjectInfo(); 됐어
	void SetupEncounters(); 됐어
	void SetupBattleProperties(); 됐어
    void SetupCutscenes();
    void SetupMapList();
    void SetGameFlag(Flag flag,bool val); 됐어
    void LoadMap(Map*map);
    void SaveMap(Map*map);
    void AddItemToPlayerInventory(ItemName item);
    Decal*CreateSprite(std::string spriteName);
    Object*CreateObjectInfo(Object*obj,std::string spriteFileName,vi2d size,Flag enableFlag=Flag::NONE,Flag disableFlag=Flag::NONE); 됐어
    vi2d grid(int x, int y);
    bool GetGameFlag(int flag); 됐어
    bool GetGameFlag(Flag flag); 됐어
    //You're probably trying to add an object to the world. Use this function inside of AddObjectToWorld(CreateObject(...))
    //You only need to use this function if you want to create an object from pre-defined OBJ_INFO variables.
    Object*CreateObject(int id,vd2d pos);
    Object* AddObjectToWorld(Object*obj);
    void LoadEncounter(Map*map,vd2d pos,int chance,int id,bool successful);
    bool OnUserUpdate(float fElapsedTime)override;
    void updateGame();
    void keyUpdates();
    void drawGame();
    ActionType GetCurrentCutsceneAction();
    void HandleRollingCounters();
    void HandleRollingCounters(int i,int(&counter)[4][3],int(&display)[4][3],Entity*member,int maxVal,int currentVal,int targetVal,bool pp=false);
    void HandleBattle();
    void HandleCutscenes();
    bool TabHeld();
    bool UpPressed();
    bool DownPressed();
    bool LeftPressed();
    bool RightPressed();
    bool BackPressed();
    bool UpHeld();
    bool DownHeld();
    bool LeftHeld();
    bool RightHeld();
    bool BackHeld();
    bool UpReleased();
    bool DownReleased();
    bool LeftReleased();
    bool RightReleased();
    bool BackReleased();
    bool PlayerCanMove();
    bool NPCCanMove();
    void UpdatePlayerTrail(vd2d newMovement,Direction newFacingDir);
    void SetupRollingHitpointCounters();
    void AdvanceMessageBox();
    //CAMERA UPDATES MUST BE LAST!!! COLLISIONS RELY ON THE GAME POSITION STATES REMAINING THE SAME!
    void cameraUpdate();
    void StartEffect(Effect*eff);
    void PopulateBattleMoveList(int partyMemberSlot,bool overworld=false);
    void SetupTargetSelect();
    //Can run this after target selection to reset states.
    void ConfirmPlayerTargetSelection();
    std::vector<Entity*> GetEntitiesInRange(int targetEnt, vd2d channelPos, Battle::Move*move);
    int CalculateSpeedGridMovementAmount(int spd);
    void PopulateMovementGrid(vd2d pos,int range);
    //Returns 0 if not found.
	int getProperty(Property prop,Battle::Move*move);
    void HandleInventoryNavigation();
    void PerformOverworldMove(Battle::Move*move,int partyMemberSlot);
    void PopulateEquipMenuItems();
    void CursorControl(int&cursor,int max);
    //Returns a version of str with a/an and a space prepended to it followed by the str itself.
	std::string A_An(std::string str,bool capitalized=false);
    void DrawTargetRangeGrid(vd2d pos,int range,Pixel outlinecol,Pixel box1col,Pixel box2col,bool connectedborder);
    void DrawTargetRangeGrid(vd2d pos,int range);
    void DrawMovementGrid(Pixel outlinecol,Pixel box1col,Pixel box2col);
    void drawCheckerboardBox(const olc::vi2d &pos, const olc::vi2d &size, olc::Pixel p = olc::WHITE, olc::Pixel alternatingCol = olc::WHITE,  const olc::vi2d &checkerboardSize = {3,3}, olc::Pixel p2 = olc::DARK_GREY, olc::Pixel p3 = olc::VERY_DARK_GREY);
    bool OverworldMenuOpen();
    void DrawRollingCounter(const olc::vi2d &pos,int val,int*rollcounter,int*rolloffset);
    void DrawGameWorld();
    void DrawDialogBox(const vi2d &pos, const vi2d &size, Pixel p, Pixel p2, Pixel p3);
    //The player's money count. It's shown in a box that is WIDTH/4 and HEIGHT/6 in size.
	void DrawMoneyBox(vf2d pos,vf2d size={(int)(WIDTH/4),(int)(HEIGHT/6)});
    void CalculateChangeInEquipmentStats(int partyMemberSlot,int itemSlot,int&equipAttack,int&equipDefense,int&newAttack,int&newDefense);
    void CalculateEquipmentStats(int partyMemberSlot,int&atk,int&def);
    std::string Wrap(std::string str,int width,bool proportional,vd2d scale);
    void DrawBattleMoveList(int partyMemberSlot);
    vf2d AutoScaleText(std::string str,int targetWidth,vf2d scale={1,1},bool prop=true);
    std::string ParseBattleMessage(Entity*ent,std::string baseStr);
    void DrawArrow();
    bool MoveCameraTowardsPoint(vd2d targetPos,PriorityDirection dir,double spd,bool secondRun=false);
    bool MoveObjectTowardsPoint(Object*obj,vd2d targetPos,PriorityDirection dir,double moveSpd,bool secondRun=false);
    int CalculateHealing(Entity*user);
    int getMemberIDComparingObject(Object*obj);
    int CalculateDamage(Entity*attacker,Entity*defender,bool includeDefenses=true);
    //Returns true if the key is meant to be continuously repeated because of being held down.
	//dir should be UP,DOWN,LEFT,RIGHT
	bool KeyRepeat(Key dir);
    bool MessageBoxAllowedToAdvance();
    void CheckGrid(int x,int y,vd2d pos,int lifetime);
    bool startsWithVowel(std::string str);
    void drawBox(const olc::vi2d &pos, const olc::vi2d &size, olc::Pixel p = olc::WHITE, olc::Pixel p2 = olc::DARK_GREY, olc::Pixel p3 = olc::VERY_DARK_GREY);
    std::string GetTargetName(int target);
    void OnTextEntryComplete(const std::string&text)override;
    void GetAnyKeyPress(olc::Key keypress)override;
    bool Collision(vd2d pos);
    void DrawInventory();
    void ChoiceMade(int choice);
    void StartCutscene(Cutscene*cutscene);
    void DrawTriggers();
    void SaveGameSaveData(int saveSlot);
    void LoadGameSaveData(int saveSlot);
    int ReadIntFromStream(std::ifstream&f);
    float ReadFloatFromStream(std::ifstream&f);
    double ReadDoubleFromStream(std::ifstream&f);
    std::string ReadStringFromStream(std::ifstream&f);
    void CenterCameraOnPlayer();
    int GetPointQuadrantRelativeToLine(vi2d x1y1,vi2d x2y2,vi2d point);
    TILE GetSafeTileData(std::vector<std::vector<TILE*>>&data);
    char GetTileDegreeSafely(std::vector<std::vector<TILE*>>&data);
};
extern SeasonI*GAME;
#endif