using Celeste.Mod.Entities;
using Celeste.Mod.LakeSideCode.FishDefs;
using Microsoft.Xna.Framework;
using Monocle;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Celeste.Mod.LakeSideCode.Triggers {

	[CustomEntity("LakeSideCode/FishingTrigger")]
	public class FishingTrigger : Trigger {

		private List<FishType> fishType = [];
		private List<FishType> requiredBait = [];
		private bool allowCatchingOnLand;
		private string requiredFlag = "";

		private static int angelDevilCounter = 0;
		private static int troutBassCounter = 1;

		private FishType lastBait = FishType.Nothing;

		public FishingTrigger(EntityData data, Vector2 offset) : base(data, offset) {
			// Fish
			fishType.Add(Enum.Parse<FishType>(data.Attr("fishType", "Nothing")));
			FishType type = Enum.Parse<FishType>(data.Attr("secondFishType", "Nothing"));
			if (type != FishType.Nothing) fishType.Add(type);
			// Bait
			for (int i = 1; i <= 4; i++) {
				type = Enum.Parse<FishType>(data.Attr($"requiredBait{(i == 1 ? "" : i.ToString())}", "Nothing"));
				if (type != FishType.Nothing) requiredBait.Add(type);
			}
			// Misc
			allowCatchingOnLand = data.Bool("allowCatchingOnLand", false);
			string reqTOD = data.Attr("minimumTimeOfDay", "Sunrise");
			if (reqTOD != "Sunrise") requiredFlag = $"LS_Catchable_{reqTOD}";
		}

		/// <summary>
		/// Determines whether the flag requirement is satisfied
		/// </summary>
		/// <returns>true if requirement is satisfied, otherwise false</returns>
		public bool FlagCheck(Session session = null) {
			session ??= SceneAs<Level>()?.Session;
			return string.IsNullOrEmpty(requiredFlag) || session?.GetFlag(requiredFlag) == true;
		}

		public FishType ChooseFish(bool inWater, Session session) {
			if (!inWater && !allowCatchingOnLand) return FishType.Nothing;
			else if (!FlagCheck(session)) return FishType.Nothing;
			else if (requiredBait.Count == 0 || requiredBait.Contains(lastBait)) {
				int i = TimeSpan.FromTicks(SceneAs<Level>().Session.Time).Seconds;

				if(fishType.Contains(FishType.Trout) && fishType.Contains(FishType.Bass)) {
					i = troutBassCounter;

					troutBassCounter++;
				}

				if(fishType.Contains(FishType.Angel) && fishType.Contains(FishType.Devil)) {
					i = angelDevilCounter;

					angelDevilCounter++;
				}
				return fishType[i % fishType.Count];
			}
			else return FishType.Nothing;
		}

		public void Baited(FishType bait) {
			lastBait = bait;
			if (requiredBait.Contains(lastBait) && FlagCheck()) {
				Scene.Add(new MiniTextbox("LAKESIDE_FISHING_BAIT_SUCCESS"));
				Audio.Play("event:/Lakeside_BaitWorks");
			}
			else {
				Scene.Add(new MiniTextbox("LAKESIDE_FISHING_BAIT_FAIL"));
			}
		}
	}
}
