using System.Collections.Generic;
using System.Linq;
using RimWorld;
using Verse;

namespace SCE
{
    public class RitualRoleBetrothed : RitualRole
    {
        /* Non-exhaustive list of usages
         * Called when                  | pawn      | ritual    | precept   | assignments
         * ------------------------------------------------------------------------------
         * creating gizmo               | all       | null      | null      | null
         * right-clicking focus         | selected  | null      | null      | null
         * filtering assignable pawns   | animals   | null      | null      | null
         * checking if ritual can start | all       | null      | null      | null
         * RRA.TryAssign                |           | null      | null      | caller
         * RRA.CandidatesForRole        | all       | null      | null      | caller
         */
        public override bool AppliesToPawn(Pawn p, out string reason, TargetInfo selectedTarget, LordJob_Ritual ritual = null, RitualRoleAssignments assignments = null, Precept_Ritual precept = null, bool skipReason = false)
        {
            if (!AppliesIfChild(p, out reason, skipReason))
            {
                return false;
            }

            if (assignments == null)
            {
                return p.relations.DirectRelations.Any(r => r.def == PawnRelationDefOf.Fiance);
            }

            var role = assignments.RoleForPawn(p);
            if (role == null)
            {
                return true;
            }

            Pawn otherPawn;
            if (role.id == RitualRoleNames.Initiator)
            {
                otherPawn = assignments.FirstAssignedPawn(RitualRoleNames.Receiver);
            }
            else
            {
                otherPawn = assignments.FirstAssignedPawn(RitualRoleNames.Initiator);
            }
            
            var betrothals = p.relations.DirectRelations.Where(rel => rel.def == PawnRelationDefOf.Fiance).ToList();
            if (betrothals.Count == 0)
            {
                if (!skipReason)
                {
                    if (otherPawn != null)
                    {
                        reason = "PawnsNotEngagedToEachOther".Translate(p.Named("PAWN"), otherPawn.Named("OTHERPAWN"));
                    }
                    else
                    {
                        reason = "PawnNotEngaged".Translate(p.Named("PAWN"));
                    }
                }
                return false;
            }

            if (otherPawn != null)
            {
                var betrothal = betrothals.FirstOrDefault(rel => rel.otherPawn == otherPawn);
                if (betrothal == null)
                {
                    if (!skipReason)
                    {
                        reason = "PawnsNotEngagedToEachOther".Translate(p.Named("PAWN"), otherPawn.Named("OTHERPAWN"));
                    }

                    return false;
                }

                // Wait a minimum of ten days after the proposal.
                int ticksLeft = RitualObligationTrigger_LewdWedding.ticksToMarriage - (Find.TickManager.TicksGame - betrothal.startTicks);
                if (ticksLeft > 0)
                {
                    if (!skipReason)
                    {
                        reason = "PawnsRecentlyEngaged".Translate(p.Named("PAWN"), otherPawn.Named("OTHERPAWN"), ticksLeft.ToStringTicksToPeriod().Named("TIMELEFT"));
                    }

                    return false;
                }
            }

            return true;
        }

        // The only place core uses this over AppliesToPawn is when generating ideo role tooltips, which doesn't apply here.
        public override bool AppliesToRole(Precept_Role role, out string reason, Precept_Ritual ritual = null, Pawn pawn = null, bool skipReason = false)
        {
            reason = null;
            return false;
        }

        protected override int PawnDesirability(Pawn pawn)
        {
            var relations = pawn.relations.DirectRelations.Where(r => r.def == PawnRelationDefOf.Fiance
                                                                      && r.otherPawn.Spawned
                                                                      && !r.otherPawn.DeadOrDowned
                                                                      && r.otherPawn.Map == pawn.Map
                                                                      && this.AppliesToPawn(r.otherPawn, out _, TargetInfo.Invalid, skipReason: true));
            if (!relations.Any())
            {
                return 0;
            }
            return (int)relations.Max(e => GenDate.DaysPassed - 10 - GenDate.TicksToDays(e.startTicks));
        }
    }
}