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

namespace Framework.ItemSystem
{
    // TODO, interface, comment
    /// <summary>
    /// An actual definitive instance of an item. This should be extended to provide template functionality
    /// for properties that should persist for an item even when it is in an inventory. For example: 
    /// number of consumable item left, ammount of gun ammo left, level or rank in item which goes up with
    /// use, damage to item etc
    /// </summary>
    public class Item : Itemlike
    {
        private string name; // The name of time
        private ItemType.Id type; // The type of the item, using the ItemType 
        private string description; // The description of the item
        private GameObject owner; // The owner of the item, TODO make it a component or ItemSlot type?

        public Item()
        {
        }

        /// <summary>
        /// Instantiates a new item with given definition and owner.
        /// </summary>
        /// <param name="definition"></param>
        /// <param name="prefab"></param>
        /// <param name="owner"></param>
        public Item(ItemDefinitionlike definition, GameObject owner) 
        {
            this.name = definition.GetName();
            this.type = definition.GetItemType();
            this.description = definition.GetDescription();
            this.owner = owner;
        }

        /// <summary>
        /// Gets the name of this item.
        /// </summary>
        /// <returns></returns>
        public string GetName()
        {
            return this.name;
        }

        /// <summary>
        /// Gets the type of this item, identified by a <see cref="ItemType.Id"/>.
        /// </summary>
        /// <returns></returns>
        public ItemType.Id GetItemType()
        {
            return type;
        }

        /// <summary>
        /// Gets the description of this item.
        /// </summary>
        /// <returns></returns>
        public string GetDescription()
        {
            return this.description;
        }

        public void SetDefinition(ItemDefinitionlike definition)
        {
            this.name = definition.GetName();
            this.type = definition.GetItemType();
            this.description = definition.GetDescription();
        }

        /// <summary>
        /// Returns the owner of this item.
        /// </summary>
        /// <returns></returns>
        public GameObject GetOwner()
        {
            return this.owner;
        }

        /// <summary>
        /// Sets the owner of this item.
        /// </summary>
        /// <param name="owner"></param>
        public void SetOwner(GameObject owner)
        {
            this.owner = owner;
        }

        /// <summary>
        /// This method should be called when this item leaves 
        /// an inventory. The method is abstract so an extended
        /// implementation of it should be provided.
        /// </summary>
        public virtual void LeaveInventory()
        { }

        /// <summary>
        /// This method should be called when this item enters
        /// an inventory The method is abstract so an extended 
        /// implementtion of it should be provided.
        /// </summary>
        public virtual void EnterInventory()
        { }

        /// <summary>
        /// Prevents this method from being called from Item.
        /// </summary>
        /// <typeparam name="ItemType">The type of the tem type.</typeparam>
        /// <param name="owner">The owner.</param>
        /// <returns></returns>
        /// <exception cref="System.MethodAccessException">Attempt to call CreateItemInstance from a concrete item type not permitted</exception>
        public Itemlike CreateItemInstance(GameObject owner)
        {
            throw new MethodAccessException("Attempt to call CreateItemInstance from a concrete item type not permitted");
        }
    }
}
