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

namespace Framework.InteractionSystem
{
    /// <summary>
    /// An object that can be interacted with by other interactables. The 
    /// process is done by passing acts/actions as messages between objects.
    /// </summary>
    public interface Interactable
    {
        GameObject GetGameObject();

        /// <summary>
        /// Gets the object that holds this interactable as a component. This 
        /// may not be applicable in all instances.
        /// </summary>
        /// <returns></returns>
        object GetSelf();

        /// <summary>
        /// Sends an action to a global group of receivers managed by a
        /// mediator.
        /// </summary>
        /// <param name="action">The action.</param>
        /// <returns></returns>
        bool Announce(Actionlike action);

        /// <summary>
        /// Only sends an action to the current exposed interactables and
        /// not the global mediator.
        /// </summary>
        /// <param name="action">The action.</param>
        /// <returns></returns>
        bool ExposedInteract(Actionlike action);
        bool ExposedInteract(Actionlike action, bool announce);

        /// <summary>
        /// Interacts only with components on this current object.
        /// </summary>
        /// <param name="action">The action.</param>
        /// <returns></returns>
        bool SelfInteract(Actionlike action);
        bool SelfInteract(Actionlike action, bool announce);

        /// <summary>
        /// Interacts directly with a gameObject.
        /// </summary>
        /// <param name="gameObject"></param>
        /// <param name="action"></param>
        /// <returns></returns>
        bool DirectInteract(GameObject gameObject, Actionlike action);
        bool DirectInteract(GameObject gameObject, Actionlike action, bool announce);

        /// <summary>
        /// Sends an action to all self interactables, current exposed 
        /// interactables and a optionally a global mediator.
        /// </summary>
        /// <param name="action">The action.</param>
        /// <returns></returns>
        bool Interact(Actionlike action);
        bool Interact(Actionlike action, bool announce);

        /// <summary>
        /// Handles reception of an action by dispatching it to a delegate
        /// method.
        /// </summary>
        /// <param name="action">The action.</param>
        /// <returns></returns>
        bool Receive(Actionlike action);

        /// <summary>
        /// Requests exposure from the object this is called on and hands
        /// exposure back to the requester parameter. This will expose
        /// all action &gt; interactable maps to the requester.
        /// </summary>
        /// <param name="requester">The requester.</param>
        void RequestExpose(Interactable requester);

        /// <summary>
        /// Exposes an action &gt; interactable map to the interactable this is
        /// called on. Gives over information to the interactable that this
        /// is called on as to which acts this the given interactable is
        /// interested in.
        /// </summary>
        /// <param name="actType">Type of the action.</param>
        /// <param name="interactable">The interactable.</param>
        void Expose(Type actType, Interactable interactable);

        /// <summary>
        /// Removes an interactable from the list of current exposed 
        /// interactables.
        /// </summary>
        /// <param name="interactable">The interactable.</param>
        void ClearExposed(Interactable interactable);
    }
}
