using Barotrauma.Items.Components;
using FarseerPhysics;
using Microsoft.Xna.Framework;
using System;
using System.Linq;

namespace Barotrauma
{
    class AIObjectiveExtinguishFire : AIObjective
    {
        public override string DebugTag => "extinguish fire";
        public override bool ForceRun => true;
        public override bool KeepDivingGearOn => true;

        private Hull targetHull;

        private AIObjectiveGetItem getExtinguisherObjective;

        private AIObjectiveGoTo gotoObjective;

        private float useExtinquisherTimer;

        public AIObjectiveExtinguishFire(Character character, Hull targetHull) : base(character, "")
        {
            this.targetHull = targetHull;
        }

        public override float GetPriority(AIObjectiveManager objectiveManager)
        {
            if (gotoObjective != null && !gotoObjective.CanBeCompleted) { return 0; }
            // Vertical distance matters more than horizontal (climbing up/down is harder than moving horizontally)
            float dist = Math.Abs(character.WorldPosition.X - targetHull.WorldPosition.X) + Math.Abs(character.WorldPosition.Y - targetHull.WorldPosition.Y) * 2.0f;
            float distanceFactor = MathHelper.Lerp(1, 0.1f, MathUtils.InverseLerp(0, 10000, dist));
            float severityFactor = MathHelper.Lerp(0, 1, MathHelper.Clamp(targetHull.FireSources.Sum(fs => fs.Size.X) / targetHull.Size.X, 0, 1));
            return MathHelper.Clamp(Priority * severityFactor * distanceFactor, 0, 100);
        }

        public override bool IsCompleted()
        {
            return targetHull.FireSources.Count == 0;
        }

        public override bool IsDuplicate(AIObjective otherObjective)
        {
            var otherExtinguishFire = otherObjective as AIObjectiveExtinguishFire;
            return otherExtinguishFire != null && otherExtinguishFire.targetHull == targetHull;
        }

        public override bool CanBeCompleted
        {
            get { return getExtinguisherObjective == null || getExtinguisherObjective.IsCompleted() || getExtinguisherObjective.CanBeCompleted; }
        }

        protected override void Act(float deltaTime)
        {
            var extinguisherItem = character.Inventory.FindItemByIdentifier("extinguisher") ?? character.Inventory.FindItemByTag("extinguisher");
            if (extinguisherItem == null || extinguisherItem.Condition <= 0.0f || !character.HasEquippedItem(extinguisherItem))
            {
                if (getExtinguisherObjective == null)
                {
                    character.Speak(TextManager.Get("DialogFindExtinguisher"), null, 2.0f, "findextinguisher", 30.0f);
                    getExtinguisherObjective = new AIObjectiveGetItem(character, "extinguisher", true);
                }
                else
                {
                    getExtinguisherObjective.TryComplete(deltaTime);
                }

                return;
            }

            var extinguisher = extinguisherItem.GetComponent<RepairTool>();
            if (extinguisher == null)
            {
                DebugConsole.ThrowError("AIObjectiveExtinguishFire failed - the item \"" + extinguisherItem + "\" has no RepairTool component but is tagged as an extinguisher");
                return;
            }

            foreach (FireSource fs in targetHull.FireSources)
            {
                bool inRange = fs.IsInDamageRange(character, MathHelper.Clamp(fs.DamageRange * 1.5f, extinguisher.Range * 0.5f, extinguisher.Range));
                if (targetHull == character.CurrentHull && (inRange || useExtinquisherTimer > 0.0f))
                {
                    useExtinquisherTimer += deltaTime;
                    if (useExtinquisherTimer > 2.0f) useExtinquisherTimer = 0.0f;

                    character.AIController.SteeringManager.Reset();
                    character.CursorPosition = fs.Position;
                    if (extinguisher.Item.RequireAimToUse)
                    {
                        character.SetInput(InputType.Aim, false, true);
                    }
                    extinguisher.Use(deltaTime, character);

                    if (!targetHull.FireSources.Contains(fs))
                    {
                        character.Speak(TextManager.Get("DialogPutOutFire").Replace("[roomname]", targetHull.Name), null, 0, "putoutfire", 10.0f);
                    }
                    return;
                }
                else
                {
                    //go to the first firesource
                    if (gotoObjective == null || !gotoObjective.CanBeCompleted || gotoObjective.IsCompleted())
                    {
                        gotoObjective = new AIObjectiveGoTo(ConvertUnits.ToSimUnits(fs.Position), character);
                    }
                    else
                    {
                        gotoObjective.TryComplete(deltaTime);
                    }
                    break;
                }
            }
        }
    }
}
