--by B O B c a t (https://steamcommunity.com/id/the_bobcat/)

require "MF_ISMoodle"

--If another mod uses the same names as these global variables, it will break the mod that is loaded first.
--I appended this mod's name to the variable names to fix the issue mention above but it's not ideal.
WeatherMoodles_Options = {}

WeatherMoodles_Options.isAltTexture = nil

WeatherMoodles_Options.enableExtreme = nil
WeatherMoodles_Options.isCombine = nil

WeatherMoodles_Options.showInside = nil

WeatherMoodles_Options.enableCloud = nil
WeatherMoodles_Options.cloudIs = nil

WeatherMoodles_Options.enableRain = nil
WeatherMoodles_Options.rainIs = nil

WeatherMoodles_Options.enableSnow = nil
WeatherMoodles_Options.snowIs = nil

WeatherMoodles_Options.enableWind = nil
WeatherMoodles_Options.windIs = nil

WeatherMoodles_Options.enableFog = nil
WeatherMoodles_Options.fogIs = nil

WeatherMoodles_Options.enableSun = nil
WeatherMoodles_Options.sunIs = nil

WeatherMoodles_Options.enableSeason = nil
WeatherMoodles_Options.seasonIs = nil

WeatherMoodles_Options.keyBind = nil

local function InitializeOptions()
	local options = PZAPI.ModOptions:create("WeatherMoodles", "Weather Moodles")
	WeatherMoodles_Options.keyBind = options:addKeyBind("keyBind", getText("UI_WeatherMoodles_Keybind"), Keyboard.KEY_RCONTROL, getText("UI_WeatherMoodles_Keybind_Tooltip"))
	
	WeatherMoodles_Options.isAltTexture = options:addTickBox("isAltTexture", getText("UI_WeatherMoodles_IsAltTex"), true, getText("UI_WeatherMoodles_IsAltTex_Tooltip"))
	
	WeatherMoodles_Options.enableExtreme = options:addTickBox("enableExtreme", getText("UI_WeatherMoodles_EnableExtreme"), true, getText("UI_WeatherMoodles_EnableExtreme_Tooltip"))
	WeatherMoodles_Options.isCombine = options:addTickBox("isCombine", getText("UI_WeatherMoodles_IsCombine"), false, getText("UI_WeatherMoodles_IsCombine_Tooltip"))
	
	WeatherMoodles_Options.showInside = options:addTickBox("showInside", getText("UI_WeatherMoodles_ShowInside"), false, getText("UI_WeatherMoodles_ShowInside_Tooltip"))
	
	options:addDescription("Good/Bad determines the moodle background color.") --this is here because combo box does not show tooltip, bug
	
	WeatherMoodles_Options.enableCloud = options:addTickBox("enableCloud", getText("UI_WeatherMoodles_EnableCloud"), true, getText("UI_WeatherMoodles_EnableCloud_Tooltip"))
	WeatherMoodles_Options.cloudIs = options:addComboBox("cloudIs", getText("UI_WeatherMoodles_CloudIs"), getText("UI_WeatherMoodles_BGColor_Tooltip"))
	WeatherMoodles_Options.cloudIs:addItem(getText("UI_WeatherMoodles_Good"), true)
	WeatherMoodles_Options.cloudIs:addItem(getText("UI_WeatherMoodles_Bad"), false)
	
	WeatherMoodles_Options.enableRain = options:addTickBox("enableRain", getText("UI_WeatherMoodles_EnableRain"), true, getText("UI_WeatherMoodles_EnableRain_Tooltip"))
	WeatherMoodles_Options.rainIs = options:addComboBox("rainIs", getText("UI_WeatherMoodles_RainIs"), getText("UI_WeatherMoodles_BGColor_Tooltip"))
	WeatherMoodles_Options.rainIs:addItem(getText("UI_WeatherMoodles_Good"), true)
	WeatherMoodles_Options.rainIs:addItem(getText("UI_WeatherMoodles_Bad"), false)
	
	WeatherMoodles_Options.enableSnow = options:addTickBox("enableSnow", getText("UI_WeatherMoodles_EnableSnow"), true, getText("UI_WeatherMoodles_EnableSnow_Tooltip"))
	WeatherMoodles_Options.snowIs = options:addComboBox("snowIs", getText("UI_WeatherMoodles_SnowIs"), getText("UI_WeatherMoodles_BGColor_Tooltip"))
	WeatherMoodles_Options.snowIs:addItem(getText("UI_WeatherMoodles_Good"), true)
	WeatherMoodles_Options.snowIs:addItem(getText("UI_WeatherMoodles_Bad"), false)
	
	WeatherMoodles_Options.enableWind = options:addTickBox("enableWind", getText("UI_WeatherMoodles_EnableWind"), true, getText("UI_WeatherMoodles_EnableWind_Tooltip"))
	WeatherMoodles_Options.windIs = options:addComboBox("windIs", getText("UI_WeatherMoodles_WindIs"), getText("UI_WeatherMoodles_BGColor_Tooltip"))
	WeatherMoodles_Options.windIs:addItem(getText("UI_WeatherMoodles_Good"), false)
	WeatherMoodles_Options.windIs:addItem(getText("UI_WeatherMoodles_Bad"), true)
	
	WeatherMoodles_Options.enableFog = options:addTickBox("enableFog", getText("UI_WeatherMoodles_EnableFog"), true, getText("UI_WeatherMoodles_EnableFog_Tooltip"))
	WeatherMoodles_Options.fogIs = options:addComboBox("fogIs", getText("UI_WeatherMoodles_FogIs"), getText("UI_WeatherMoodles_BGColor_Tooltip"))
	WeatherMoodles_Options.fogIs:addItem(getText("UI_WeatherMoodles_Good"), false)
	WeatherMoodles_Options.fogIs:addItem(getText("UI_WeatherMoodles_Bad"), true)
	
	WeatherMoodles_Options.enableSun = options:addTickBox("enableSun", getText("UI_WeatherMoodles_EnableSun"), true, getText("UI_WeatherMoodles_EnableSun_Tooltip"))
	WeatherMoodles_Options.sunIs = options:addComboBox("sunIs", getText("UI_WeatherMoodles_SunIs"), getText("UI_WeatherMoodles_BGColor_Tooltip"))
	WeatherMoodles_Options.sunIs:addItem(getText("UI_WeatherMoodles_Good"), true)
	WeatherMoodles_Options.sunIs:addItem(getText("UI_WeatherMoodles_Bad"), false)
	
	WeatherMoodles_Options.enableSeason = options:addTickBox("enableSeason", getText("UI_WeatherMoodles_EnableSeason"), false, getText("UI_WeatherMoodles_EnableSeason_Tooltip"))
	WeatherMoodles_Options.seasonIs = options:addComboBox("seasonIs", getText("UI_WeatherMoodles_SeasonIs"), getText("UI_WeatherMoodles_BGColor_Tooltip"))
	WeatherMoodles_Options.seasonIs:addItem(getText("UI_WeatherMoodles_Good"), true)
	WeatherMoodles_Options.seasonIs:addItem(getText("UI_WeatherMoodles_Bad"), false)

	--Triggered whenever the user applies settings in the mod option menu. 
	options.apply = function (self)
		if getPlayer() then
			UpdateThresholds()	--Needed this because colors were getting broken if option changed in-game.
			print("UPDATED")
		end
	end
end
InitializeOptions()

--Moodle creation order determines the in-game order of them.
MF.createMoodle("Season")
--Extreme Weather
MF.createMoodle("WeatherStorm")
MF.createMoodle("WeatherBlizzard")
MF.createMoodle("WeatherTropicalStorm")

--Weather Conditions
MF.createMoodle("WeatherSun")	--This will be next to cloud, to keep the order consistent, because they are mutually exclusive. Room for improvement here in hindsight.
MF.createMoodle("WeatherCloud")
MF.createMoodle("WeatherRain")
MF.createMoodle("WeatherSnow")
MF.createMoodle("WeatherWind")
MF.createMoodle("WeatherFog")

isPlayerValid = false
isExtremeWeather = false
--isSeasonGood = { [1]=1, [2]=0 } --old. binary moodle level

--Hotkey
--Use this a master switch for showing/hiding moodles. Still respects the settings in ModOptions.
WeatherMoodles_Options.isOn = true

local function KeyUp(keynum)
	if keynum == WeatherMoodles_Options.keyBind:getValue() then
		WeatherMoodles_Options.isOn = not WeatherMoodles_Options.isOn
	end
end

--This function is not local. Because we're calling it from the ModOptions file.
function UseAltTextures()
	local selTexDir = nil
	if WeatherMoodles_Options.isAltTexture.value then selTexDir = "media/ui/alt/" else selTexDir = "media/ui/" end
	for t = 1, 2 do
		for i = 1, 4 do
			MF.getMoodle("Season"):setPicture(t, i, getTexture(selTexDir .. "SeasonDefault.png"))
			MF.getMoodle("WeatherCloud"):setPicture(t, i, getTexture(selTexDir .. "WeatherStorm.png"))
			MF.getMoodle("WeatherCloud"):setPicture(t, i, getTexture(selTexDir .. "WeatherBlizzard.png"))
			MF.getMoodle("WeatherCloud"):setPicture(t, i, getTexture(selTexDir .. "WeatherTropicalStorm.png"))
			MF.getMoodle("WeatherCloud"):setPicture(t, i, getTexture(selTexDir .. "WeatherCloud.png"))
			MF.getMoodle("WeatherRain"):setPicture(t, i, getTexture(selTexDir .. "WeatherRain.png"))
			MF.getMoodle("WeatherSnow"):setPicture(t, i, getTexture(selTexDir .. "WeatherSnow.png"))
			MF.getMoodle("WeatherWind"):setPicture(t, i, getTexture(selTexDir .. "WeatherWind.png"))
			MF.getMoodle("WeatherFog"):setPicture(t, i, getTexture(selTexDir .. "WeatherFog.png"))
			MF.getMoodle("WeatherSun"):setPicture(t, i, getTexture(selTexDir .. "WeatherSun.png"))
		end
	end
end

local function SwitchSeason(seasonName)
	local selTexDir = nil
	local moodleName = nil
	local titleText = nil
	if WeatherMoodles_Options.isAltTexture.value then selTexDir = "media/ui/alt/" else selTexDir = "media/ui/" end

	if seasonName == "Spring" then moodleName = "SeasonSpring"
	elseif seasonName == "Early Summer" then moodleName = "SeasonEarlySummer"
	elseif seasonName == "Late Summer" then moodleName = "SeasonLateSummer"
	elseif seasonName == "Autumn" then moodleName = "SeasonAutumn"
	elseif seasonName == "Winter" then moodleName = "SeasonWinter"
	else moodleName = "SeasonDefault"
	end

	for t = 1, 2 do
		for i = 1, 4 do
			MF.getMoodle("Season"):setPicture(t, i, getTexture(selTexDir .. moodleName .. ".png"))
			MF.getMoodle("Season"):setTitle(t ,i, getText("Moodles_" .. moodleName .. "_Good_lvl4"))	--Must set the descriptions for "bad" if I ever add flavor text
		end
	end
end

--!!!should rename sun related variables!!!
local function SwitchSunMoon(isSun)
	local selTexDir = nil
	local moodleName = nil
	local titleText = nil
	if WeatherMoodles_Options.isAltTexture.value then selTexDir = "media/ui/alt/" else selTexDir = "media/ui/" end
	if isSun then moodleName = "WeatherSun" else moodleName = "WeatherMoon" end
	for t = 1, 2 do
		for i = 1, 4 do
			MF.getMoodle("WeatherSun"):setPicture(t, i, getTexture(selTexDir .. moodleName .. ".png"))
			MF.getMoodle("WeatherSun"):setTitle(t, i, getText("Moodles_" .. moodleName .. "_Good_lvl4"))	--Must set the descriptions for "bad" if I ever add flavor text
		end
	end
end

--This function is not local. Because we're calling it from the ModOptions file.
function UpdateThresholds()

	if WeatherMoodles_Options.seasonIs:getValue() == 1 then
		MF.getMoodle("Season"):setThresholds(nil, nil, nil, nil, 0.001, 0.25, 0.50, 0.75)
	else
		MF.getMoodle("Season"):setThresholds(0.25, 0.50, 0.75, 0.999, nil, nil, nil, nil)
	end

	if WeatherMoodles_Options.cloudIs:getValue() == 1 then
		MF.getMoodle("WeatherCloud"):setThresholds(nil, nil, nil, nil, 0.1, 0.25, 0.50, 0.75)
	else
		MF.getMoodle("WeatherCloud"):setThresholds(0.25, 0.50, 0.75, 0.9, nil, nil, nil, nil)
	end

	if WeatherMoodles_Options.rainIs:getValue() == 1 then
		MF.getMoodle("WeatherRain"):setThresholds(nil, nil, nil, nil, 0.001, 0.25, 0.50, 0.75)
	else
		MF.getMoodle("WeatherRain"):setThresholds(0.25, 0.50, 0.75, 0.999, nil, nil, nil, nil)
	end
	
	if WeatherMoodles_Options.snowIs:getValue() == 1 then
		MF.getMoodle("WeatherSnow"):setThresholds(nil, nil, nil, nil, 0.001, 0.25, 0.50, 0.75)
	else
		MF.getMoodle("WeatherSnow"):setThresholds(0.25, 0.50, 0.75, 0.999, nil, nil, nil, nil)
	end
	
	if WeatherMoodles_Options.windIs:getValue() == 1 then
		MF.getMoodle("WeatherWind"):setThresholds(nil, nil, nil, nil, 0.02, 0.25, 0.50, 0.75)
	else
		MF.getMoodle("WeatherWind"):setThresholds(0.25, 0.50, 0.75, 0.98, nil, nil, nil, nil)
	end
	
	if WeatherMoodles_Options.fogIs:getValue() == 1 then
		MF.getMoodle("WeatherFog"):setThresholds(nil, nil, nil, nil, 0.02, 0.25, 0.50, 0.75)
	else
		MF.getMoodle("WeatherFog"):setThresholds(0.25, 0.50, 0.75, 0.98, nil, nil, nil, nil)
	end
	
	if WeatherMoodles_Options.sunIs:getValue() == 1 then
		MF.getMoodle("WeatherSun"):setThresholds(nil, nil, nil, nil, 0.1, nil, nil, 0.9)
	else
		MF.getMoodle("WeatherSun"):setThresholds(0.1, nil, nil, 0.9, nil, nil, nil, nil)
	end

end

local function HideMoodle(moodleName, optionsWeatherIs) --this sets a value to the moodle. if a moodle has threshold at values 0 or 1, this will not work correctly, e.g. the season moodle. so i set the threshold of the season moodle to not 0/1. this will cause a one day delay when season changes.
	if optionsWeatherIs ~= 1 then
		MF.getMoodle(moodleName):setValue(1)
	else
		MF.getMoodle(moodleName):setValue(0)
	end
end

--MoodleFramework dev said that MF.getMoodle() doesn't work without a valid player. So we check for that before starting. This is called by an event, check the end of file.
local function ValidatePlayer(playerIndex, player)
	if player == getPlayer() then
		isPlayerValid = true
		UpdateThresholds()
		UseAltTextures()
		SwitchSunMoon(ClimateManager.getInstance():getNightStrength() < 0.5)
		SwitchSeason(ClimateManager.getInstance():getSeasonName())
	else
		print("Player is not valid. Cannot run the mod.")
	end
end

function HideExtremeWeather()
	isExtremeWeather = false
	--0.5 is the default value for MoodleFramework.
	MF.getMoodle("WeatherStorm"):setValue(0.5)
	MF.getMoodle("WeatherBlizzard"):setValue(0.5)
	MF.getMoodle("WeatherTropicalStorm"):setValue(0.5)
end

local function ExtremeWeather(climateManager)
	local stageID = climateManager:getWeatherPeriod():getCurrentStageID()
	--I would use a switch statement if it existed.
	--And I don't like the handmade switch statements.
	--Base game weather stages
	--[[
    WEATHER_STAGE = ID
    STAGE_START = 0;
    STAGE_SHOWERS = 1;
    STAGE_HEAVY_PRECIP = 2;
    STAGE_STORM = 3;
    STAGE_CLEARING = 4;
    STAGE_MODERATE = 5;
    STAGE_DRIZZLE = 6;
    STAGE_BLIZZARD = 7;
    STAGE_TROPICAL_STORM = 8;
    STAGE_INTERMEZZO = 9;
    STAGE_MODDED = 10;
    STAGE_KATEBOB_STORM = 11;
    STAGE_MAX = 12;
    ]]--
	if stageID == 3 or stageID == 7 or stageID == 8 then
		isExtremeWeather = true
		if stageID == 3 then MF.getMoodle("WeatherStorm"):setValue(0)
		elseif stageID == 7 then MF.getMoodle("WeatherBlizzard"):setValue(0)
		elseif stageID == 8 then MF.getMoodle("WeatherTropicalStorm"):setValue(0)
		end
	else HideExtremeWeather() end
end

local function EveryHours()
	SwitchSunMoon(ClimateManager.getInstance():getNightStrength() < 0.5)
end
--[[
local function UpdateSeason()
	if WeatherMoodles_Options.enableSeason.value then
		local seasonProgression = ClimateManager.getInstance():getSeasonProgression()
		--MF.getMoodle("Season"):setValue(isSeasonGood[WeatherMoodles_Options.seasonIs:getValue()])			--old. binary moodle level --converting 1 to 1 and 2 to 0 because ModOptions starts dropdown index from 1 *sigh* 
		if WeatherMoodles_Options.seasonIs:getValue() ~= 1 then seasonProgression = 1 - seasonProgression end
		MF.getMoodle("Season"):setValue(seasonProgression)
		SwitchSeason(ClimateManager.getInstance():getSeasonName())
	else
		HideMoodle("Season", WeatherMoodles_Options.seasonIs:getValue())
	end
end
]]--

--Main function
local function UpdateWeatherMoodles(climateManager)

	local player = getPlayer()
	if isPlayerValid then
	
		local cloudIntensity = climateManager:getCloudIntensity()
		local rainIntensity = climateManager:getRainIntensity()
		local snowIntensity = climateManager:getSnowIntensity()
		local windIntensity = climateManager:getWindIntensity()
		local fogIntensity = climateManager:getFogIntensity()
		local isSunny = false
		local isSunnyVal = { [true]=1, [false]=0 }
		local seasonProgression = ClimateManager.getInstance():getSeasonProgression()

		if WeatherMoodles_Options.enableExtreme.value then ExtremeWeather(climateManager)
		else HideExtremeWeather() end --!!!put this somewhere better!!!
		--!!!this does not look pretty. find another way!!!
		if not player:isOutside() and not WeatherMoodles_Options.showInside.value or not WeatherMoodles_Options.isOn then
			HideExtremeWeather()
			HideMoodle("Season", WeatherMoodles_Options.seasonIs:getValue())
			HideMoodle("WeatherCloud", WeatherMoodles_Options.cloudIs:getValue())
			HideMoodle("WeatherRain", WeatherMoodles_Options.rainIs:getValue())
			HideMoodle("WeatherSnow", WeatherMoodles_Options.snowIs:getValue())
			HideMoodle("WeatherWind", WeatherMoodles_Options.windIs:getValue())
			HideMoodle("WeatherFog", WeatherMoodles_Options.fogIs:getValue())
			HideMoodle("WeatherSun", WeatherMoodles_Options.sunIs:getValue())
		else
			if WeatherMoodles_Options.isCombine.value and isExtremeWeather then
				HideMoodle("WeatherCloud", WeatherMoodles_Options.cloudIs:getValue())
				HideMoodle("WeatherRain", WeatherMoodles_Options.rainIs:getValue())
				HideMoodle("WeatherSnow", WeatherMoodles_Options.snowIs:getValue())
				HideMoodle("WeatherWind", WeatherMoodles_Options.windIs:getValue())
				--HideMoodle("WeatherFog", WeatherMoodles_Options.fogIs:getValue())
				HideMoodle("WeatherSun", WeatherMoodles_Options.sunIs:getValue())
			else
				if WeatherMoodles_Options.enableCloud.value then
					if WeatherMoodles_Options.cloudIs:getValue() ~= 1 then cloudIntensity = 1 - cloudIntensity end
					MF.getMoodle("WeatherCloud"):setValue(cloudIntensity)
				else HideMoodle("WeatherCloud", WeatherMoodles_Options.cloudIs:getValue()) end

				if WeatherMoodles_Options.enableRain.value then
					if WeatherMoodles_Options.rainIs:getValue() ~= 1 then rainIntensity = 1 - rainIntensity end		--Inverting the intensities to comply with how MoodleFramework works so we can implement toggling the "Good/Bad" moodles.
					MF.getMoodle("WeatherRain"):setValue(rainIntensity)
				else HideMoodle("WeatherRain", WeatherMoodles_Options.rainIs:getValue()) end

				if WeatherMoodles_Options.enableSnow.value then
					if WeatherMoodles_Options.snowIs:getValue() ~= 1 then snowIntensity = 1 - snowIntensity end
					MF.getMoodle("WeatherSnow"):setValue(snowIntensity)
				else HideMoodle("WeatherSnow", WeatherMoodles_Options.snowIs:getValue()) end

				if WeatherMoodles_Options.enableWind.value then
					if WeatherMoodles_Options.windIs:getValue() ~= 1 then windIntensity = 1 - windIntensity end
					MF.getMoodle("WeatherWind"):setValue(windIntensity)
				else HideMoodle("WeatherWind", WeatherMoodles_Options.windIs:getValue()) end

				if WeatherMoodles_Options.enableFog.value then
					if WeatherMoodles_Options.fogIs:getValue() ~= 1 then fogIntensity = 1 - fogIntensity end
					MF.getMoodle("WeatherFog"):setValue(fogIntensity)
				else HideMoodle("WeatherFog", WeatherMoodles_Options.fogIs:getValue()) end

				if rainIntensity == 0 and snowIntensity == 0 then
					if WeatherMoodles_Options.cloudIs:getValue() == 1 and cloudIntensity < 0.1 then isSunny = true
					elseif WeatherMoodles_Options.cloudIs:getValue() ~= 1 and cloudIntensity > 0.9 then isSunny = true	--Accounting for inverted intensity
					end
				end
				if WeatherMoodles_Options.enableSun.value and isSunny then
					if WeatherMoodles_Options.sunIs:getValue() ~= 1 then isSunny = false end
					MF.getMoodle("WeatherSun"):setValue(isSunnyVal[isSunny])	--setValue doesn't take booleans, so we're converting isSunny.
				else HideMoodle("WeatherSun", WeatherMoodles_Options.sunIs:getValue())
				end
				if WeatherMoodles_Options.enableSeason.value then
					--MF.getMoodle("Season"):setValue(isSeasonGood[WeatherMoodles_Options.seasonIs:getValue()])			--old. binary moodle level --converting 1 to 1 and 2 to 0 because ModOptions starts dropdown index from 1 *sigh* 
					if WeatherMoodles_Options.seasonIs:getValue() ~= 1 then seasonProgression = 1 - seasonProgression end
					MF.getMoodle("Season"):setValue(seasonProgression)
					SwitchSeason(ClimateManager.getInstance():getSeasonName())
				else
					HideMoodle("Season", WeatherMoodles_Options.seasonIs:getValue())
				end
			end
		end
	else print("Player is not valid. Cannot update the weather.")
	end
end

--Call our ValidatePlayer function when this event fires
Events.OnCreatePlayer.Add(ValidatePlayer)

--Call our main function when this event fires. This is how we update.
Events.OnClimateTick.Add(UpdateWeatherMoodles)

Events.EveryHours.Add(EveryHours)

Events.OnKeyPressed.Add(KeyUp)

--Events.EveryDays.Add(UpdateSeason) --calling it from the main function for now