using Framework.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;

namespace Framework.ItemSystem
{
    /// <summary>
    /// The action of exposing an inventory to other components. 
    /// </summary>
    public class ExposeInventory : CoreAction
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="ExposeInventory"/> class.
        /// </summary>
        /// <param name="sender">The sender.</param>
        public ExposeInventory(CoreBehaviour sender)
            : base(sender)
        {
        }

        /// <summary>
        /// Gets the inventory.
        /// </summary>
        /// <returns></returns>
        public Inventory GetInventory()
        {
            return (Inventory)GetSender();
        }
    }

    /// <summary>
    /// The action of setting up the item properties on a newly created 
    /// physical item gameObject. TODO: Move to a group of item actions.
    /// </summary>
    public class SetupItemProperties : CoreAction
    {
        private Itemlike item; // The item object to apply to the gameObject
        private CoreBehaviour holder; // The entity component holder to apply to the gameObject

        /// <summary>
        /// Initializes a new instance of the <see cref="SetupItemProperties"/> class.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="item">The item.</param>
        /// <param name="holder">The holder.</param>
        public SetupItemProperties(CoreBehaviour sender, Itemlike item, CoreBehaviour holder)
            : base(sender)
        {
            this.item = item;
            this.holder = holder;
        }

        /// <summary>
        /// Gets the item.
        /// </summary>
        /// <returns></returns>
        public Itemlike GetItem()
        {
            return this.item;
        }

        /// <summary>
        /// Gets the holder.
        /// </summary>
        /// <returns></returns>
        public CoreBehaviour GetHolder()
        {
            return this.holder;
        }
    }

    /// <summary>
    /// This component stores items that belong to this entity or gameObject.
    /// Items from this component can be equip to <see cref="ItemSlot"/> components
    /// to be used.
    /// </summary>
    public class Inventory : CoreBehaviour
    {
        public string[] editorItemsToAdd; // Item names in the editor to be added
        private List<Itemlike> items; // The collection of items

        /// <summary>
        /// Gets the item.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <returns></returns>
        public Itemlike GetItem(string name)
        {
            return this.items.FirstOrDefault(i => i.GetName() == name);
        }

        protected override void InnerAwake()
        {
            this.items = new List<Itemlike>();
            for (int i = 0; i < editorItemsToAdd.Length; i++)
            {
                this.items.Add(ItemDefinitionsLocator.Get().GetItemDefinition(editorItemsToAdd[i]).CreateItemInstance(this.gameObject));
            }

            AddActionHandler<PickupItem>(AddItem);
            AddActionHandler<DropItem>(RemoveItem);
        }

        protected override void InnerStart()
        {
            SelfInteract(new ExposeInventory(this));
        }

        private void AddItem(PickupItem action)
        {
            this.items.Add(action.GetItem());
        }

        private void RemoveItem(DropItem action)
        {
            if(this.items.Contains(action.GetItem()))
            {
                GameObject itemGameObject = (GameObject)GameObject.Instantiate(Resources.Load(action.GetItem().GetName()), this.transform.position, new Quaternion());
                DirectInteract(itemGameObject, new SetupItemProperties(this, action.GetItem(), this));
                this.items.Remove(action.GetItem());
            }
        }
    }
}
