#include <Geode/Geode.hpp>
#include <Geode/binding/FMODAudioEngine.hpp>
#include <Geode/modify/MenuLayer.hpp>
#include <Geode/modify/AccountRegisterLayer.hpp>
#include <Geode/modify/CCNode.hpp>
#include <Geode/modify/GJBaseGameLayer.hpp>
#include <Geode/modify/GameStatsManager.hpp>
#include <Geode/modify/GameManager.hpp>
#include <Geode/modify/GameLevelManager.hpp>
#include <Geode/modify/MoreSearchLayer.hpp>
#include <Geode/modify/SongSelectNode.hpp>
#include <Geode/modify/EditorUI.hpp>
#include <Geode/modify/LoadingLayer.hpp>
#include <Geode/modify/PlayLayer.hpp>
#include <Geode/ui/Layout.hpp>
#include <Geode/ui/GeodeUI.hpp>

using namespace geode::prelude;

class $modify(SNMenuLayer, MenuLayer) {
	bool init() {
		if (!MenuLayer::init()) return false;

		auto win = CCDirector::sharedDirector()->getWinSize();

		if (auto rem = this->getChildByID("main-menu-bg")) { rem->setVisible(false); }
		if (auto rem = this->getChildByID("right-side-menu")) { rem->setVisible(false); }
		if (auto rem = this->getChildByID("main-title")) { rem->setVisible(false); }
		if (auto rem = this->getChildByID("social-media-menu")) { rem->setVisible(false); }
		if (auto rem = this->getChildByID("more-games-menu")) { rem->setVisible(false); }
		if (auto rem = this->getChildByID("close-menu")) { rem->setVisible(false); }
		if (auto rem = this->getChildByID("player-username")) { rem->setVisible(false); }
		if (auto rem = this->getChildByID("profile-menu")) { rem->setVisible(false); }

		if (auto rem = this->getChildByID("bottom-menu")) {
			if (auto btn = rem->getChildByID("geode.loader/geode-button")) { btn->removeFromParent(); }
			if (auto btn = rem->getChildByID("newgrounds-button")) { btn->removeFromParent(); }

            rem->setLayout(
                geode::ColumnLayout::create()
                    ->setGap(32.0f)
                    ->setAxisAlignment(geode::AxisAlignment::Center)
                    ->setCrossAxisAlignment(geode::AxisAlignment::Center)
					->setAxisReverse(true)

            );

            auto win = CCDirector::sharedDirector()->getWinSize();
            rem->setPosition({ win.width * 0.95f, win.height * 0.30f });
			rem->setContentSize({ 40.0f, 150.0f });
            rem->updateLayout();

			auto box = cocos2d::CCDrawNode::create();
			box->setID("bottom-menu-bg");
			box->setPosition({ win.width * 0.96f, win.height * 0.08f });
			box->drawRect({-30, -30}, {30, rem->getContentSize().height + 20}, {0,0,0,0.75f}, true, {0,0,0,0.75f}); 
			this->addChild(box, -1);
		}

		if (auto accountID = GJAccountManager::sharedState()->m_accountID) {
    		if (auto menu = this->getChildByID("bottom-menu")) {
        		auto profile = CCMenuItemSpriteExtra::create(
            		CCSprite::createWithSpriteFrameName("GJ_profileButton_001.png"),
            		this, menu_selector(MenuLayer::onMyProfile)
        		);
        		profile->setID("starnight-button");
        		menu->addChild(profile);
        		menu->updateLayout();
    		}
		} else {
			if (auto menu = this->getChildByID("bottom-menu")) {
				auto profile = CCMenuItemSpriteExtra::create(
					CCSprite::createWithSpriteFrameName("GJ_profileButton_001.png"),
					this, menu_selector(SNMenuLayer::openAccount)
				);
				profile->setID("starnight-profile");
				menu->addChild(profile);
				menu->updateLayout();
			}
		}

		auto bmenu = this->getChildByID("bottom-menu");
		auto snSettings = CCMenuItemSpriteExtra::create(
			CCSprite::createWithSpriteFrameName("geode.loader/geode-logo-outline-gold.png"),
			this, menu_selector(SNMenuLayer::onSettings)
		);
		snSettings->setID("starnight-settings");
		bmenu->addChild(snSettings);
		bmenu->updateLayout();

		if (auto m = this->getChildByID("main-menu")) {
			m->setPositionY(m->getPositionY() - 20.f);
		}

		auto bg = CCSprite::create("background.png"_spr);
		bg->setID("starnight-background");
		bg->setPosition({ win.width / 2, win.height / 2 });
		bg->setScale(1.25f);
		this->addChild(bg, -100);

		auto title = CCSprite::create("title.png"_spr);
		title->setID("starnight-title");
		title->setPosition({ win.width / 2, win.height - 70.f });
		this->addChild(title, 10);

		auto sideMenu = CCMenu::create();
		sideMenu->setID("starnight-menu");
		sideMenu->setPosition({ 25.f, win.height / 2 });
		this->addChild(sideMenu, 10);

		auto creditSpr = CCSprite::createWithSpriteFrameName("GJ_infoBtn_001.png");
		creditSpr->setScale(0.75f);
		auto credits = CCMenuItemSpriteExtra::create(
			creditSpr, this, menu_selector(SNMenuLayer::openCredits)
	    );
		credits->setID("starnight-credits");
		sideMenu->addChild(credits, 10);

		auto feedbackSpr = CCSprite::createWithSpriteFrameName("GJ_infoBtn_001.png");
		feedbackSpr->setScale(0.75f);
		feedbackSpr->setColor({ 0, 255, 0 });
		auto feedback = CCMenuItemSpriteExtra::create(
			feedbackSpr, this, menu_selector(SNMenuLayer::onFeedback)
		);
		feedback->setID("starnight-feedback");
		feedback->setPositionY(sideMenu->getChildByID("starnight-credits")->getPositionY() - 40.f);
		sideMenu->addChild(feedback, 10);

		std::string ver = "Version " + Mod::get()->getVersion().toNonVString(true);
		auto version = CCLabelBMFont::create(
			ver.c_str(), "goldFont.fnt"
		);
		version->setID("starnight-version");
		version->setPosition({ win.width / 2, 30.f });
		version->setScale(0.5f);
		this->addChild(version, 10);

		return true;
	}

    void onSettings(CCObject*) {
        geode::openSettingsPopup(Mod::get(), true);
    }

	void openCredits(CCObject*) {
		FLAlertLayer::create(
			"Credits",
			"<cy>Starnight</c> by: <co>jarvisdevil</c>\n"
			"<cf>Most textures made using Asterveila's PackGen</c>\n"
			"<cp>Built-in hacks provided by Eclipse Menu</c>\n"
			"<cc>Built from Cvolton's GDPS core.</c>",
			"OK"
		)->show();
	}

	void onFeedback(CCObject*) {
		geode::createQuickPopup(
    		"Feedback",
    		"<cy>Starnight is still a work in progress.</c>\n"
			"<cf>If you have suggestions or find issues/bugs, let me know please!</c>",
    		"Nah", "Yeah",
    		[](auto, bool btn2) {
        		if (btn2) {
        			geode::utils::web::openLinkInBrowser("https://localhost/feedback");
        		}
    		}
		);
	}

	void openAccount(CCObject*) {
    	FLAlertLayer::create(
			"Hey!",
			"<cy>You must login to view your profile.</c>\n<cg>Login by going into [Settings] -> [Account] -> [Log in]</c>",
			"OK"
		)->show();
	}
};

class $modify(SNLoadingLayer, LoadingLayer) {
	bool init(bool refresh) {
		if (!LoadingLayer::init(refresh)) return false;
		auto win = CCDirector::sharedDirector()->getWinSize();

		if (auto rem = this->getChildByID("gd-logo")) { rem->setVisible(false); }
		if (auto rem = this->getChildByID("robtop-logo")) { rem->setVisible(false); }
		if (auto rem = this->getChildByID("bg-texture")) { rem->setVisible(false); }
		
		return true;
	}
};

class $modify(SNAccountRegisterLayer, AccountRegisterLayer) {
	void registerAccountFinished() {
		AccountRegisterLayer::registerAccountFinished();
		geode::utils::web::openLinkInBrowser("http://localhost/starnightdatabase/tools/account/activateAccount.php");
	}
};

class $modify(SNCCNode, CCNode) {
	void onEnter() {
		CCNode::onEnter();

		auto allowed = std::vector<std::string> {
			"background", "bg", "main-menu-bg",
			"GJCommentListLayer", "icon-background"
		};
		for (const auto& name : allowed) {
			auto bg = this->getChildByID(name);
			if (!bg) continue;	
			auto sprite = typeinfo_cast<CCSprite*>(bg);
			auto sprite2 = typeinfo_cast<CCScale9Sprite*>(bg);
			if (!sprite && !sprite2) continue;

			if (sprite) sprite->setColor({27, 0, 51});
			//if (sprite2) sprite2->setColor({27, 0, 51});
		}
	}
};

class $modify(SNBaseGameLayer, GJBaseGameLayer) {
    bool shouldExitHackedLevel() {
		return false;
	}
};

class $modify(SNGameManager, GameManager) {
	bool isColorUnlocked(int key, UnlockType type) {
		if (GameManager::isColorUnlocked(key, type)) return true;
		return true;
	}
	bool isIconUnlocked(int key, IconType type) {
		if (GameManager::isIconUnlocked(key, type)) return true;
		return true;
	}
	bool getUGV(const char* key) {
		if (GameManager::getUGV(key)) return true;

        return strcmp(key, "11") == 0 || strcmp(key, "20") == 0
            || strcmp(key, "34") == 0 || strcmp(key, "35") == 0;
	}
    gd::string getMenuMusicFile() {
    	auto selected = Mod::get()->getSettingValue<std::string>("menuLoop");

    	if (selected == "Anamanaguchi - Helix Nebula") {
     	    return "menuLoop.mp3";
    	}
    	if (selected == "Renard - Sinisterrrrrrrr") {
        	return "menuLoop2.mp3";
    	}
    	if (selected == "Kisma - We Are") {
        	return "menuLoop3.mp3";
    	}
    	if (selected == "Toby Fox - CORE") {
        	return "menuLoop4.mp3";
    	}
    	if (selected == "Nintendo - Todays Results (Pikmin 3 OST)") {
        	return "menuLoop5.mp3";
    	}
        return GameManager::getMenuMusicFile();
    }
};

class $modify(SNGameStatsManager, GameStatsManager) {
    bool isItemUnlocked(UnlockType type, int key) {
        if (GameStatsManager::isItemUnlocked(type, key)) return true;
        return true;
    }
};

class $modify(SNGameLevelManager, GameLevelManager) {
	GJGameLevel* getMainLevel(int levelID, bool dontGetLevelString) {
		auto level = GameLevelManager::getMainLevel(levelID, dontGetLevelString);
		level->m_requiredCoins = 0;
		return level;
	}
};

class $modify(SNPlayLayer, PlayLayer) {
	void levelComplete() {
		auto selected = Mod::get()->getSettingValue<bool>("clearSFX");
		if (selected) {
			FMODAudioEngine::sharedEngine()->playEffect("clear.mp3"_spr);
		}
		PlayLayer::levelComplete();
	}
};