﻿using EnergyShell.GameObjects.Actors.Animation;
using EnergyShell.GameObjects.Actors.Zombie;
using EnergyShell.Physics;
using SFML.Graphics;
using ShellUtil;
using ShellUtil.Content;

namespace EnergyShell.GameObjects.Actors
{
    /// <summary>
    /// Implements an zombie entity.
    /// </summary>
    public sealed class ZombieEntity
    {
        /// <summary>
        /// The objectives for the zombie entity.
        /// </summary>
        private readonly AiObjectives objectives;

        /// <summary>
        /// The radius of the zombie collidable.
        /// </summary>
        private const int ZombieCollisionRadius = 8;

        /// <summary>
        /// The actors collidable body.
        /// </summary>
        private readonly CollidableActor collidableActor;

        /// <summary>
        /// The zombie movement controller.
        /// </summary>
        private readonly IMovementController movementController;

        /// <summary>
        /// The paper doll used to draw and animate the zombie entity.
        /// </summary>
        private readonly PaperDoll paperDoll;

        /// <summary>
        /// The animation controller.
        /// </summary>
        private readonly PaperDollAnimationController animationController;

        /// <summary>
        /// Initializes a new instance of the <see cref="ZombieEntity" /> class.
        /// </summary>
        /// <param name="renderTarget">The render target.</param>
        /// <param name="objectives">The objectives for this zombie.</param>
        /// <param name="bodyWorld">The world.</param>
        /// <param name="initialPosition">The initial position of the zombie entity.</param>
        /// <param name="textureHeap">The texture heap.</param>
        public ZombieEntity(
            IRenderTarget renderTarget, AiObjectives objectives, IBodyWorld bodyWorld, Vector2 initialPosition,
            IContentHeap<Texture> textureHeap)
        {
            this.objectives = objectives;
            this.collidableActor = new CollidableActor(
                bodyWorld, ZombieCollisionRadius, initialPosition, CollisionGroup.Group1 | CollisionGroup.Group3);

            this.movementController =
                new ZombieMovementController(this.collidableActor.BodyController, this.objectives);

            Sprite zombieHead = new Sprite(textureHeap.GetContent("Character/Zombie.png"));
            Sprite zombieBody = new Sprite(textureHeap.GetContent("Character/Zombie.png"));
            AnimationDefinition headDefinition =
                AnimationDefinitionFactory.CreateZombieHeadAnimationDefinition();
            AnimationDefinition bodyDefinition =
                AnimationDefinitionFactory.CreateZombieBodyAnimationDefinition();
            this.paperDoll = new PaperDoll(
                renderTarget, this.collidableActor.BodyData, zombieHead, zombieBody, headDefinition,
                bodyDefinition);
            this.animationController = new PaperDollAnimationController(this.paperDoll);
        }

        /// <summary>
        /// Updates this instance.
        /// </summary>
        public void Update()
        {
            this.movementController.Update();
            this.animationController.Update(
                this.movementController.CurrentFaceDirection, this.movementController.CurrentMovementState);
        }

        /// <summary>
        /// Draws the specified interpolation.
        /// </summary>
        /// <param name="interpolation">The interpolation.</param>
        public void Draw(double interpolation)
        {
            this.paperDoll.Draw(interpolation);
        }
    }
}
