using System.Collections.Generic;
using UnityEngine;
using System.Collections;


public class AntaresAddonController : MonoBehaviour
{
    public static AntaresAddonController thisScript;
    public int maxDescLinesCount = 1024;
    public bool freeMemoryOnPlay = true;
    protected GameObject mTagsCollector;
    protected static Dictionary<string, List<GameObject>> multitagedObjects = new Dictionary<string, List<GameObject>>();

    /// <summary>
    /// System method. Do not use it yourself
    /// </summary>
    /// <returns></returns>
    public static AntaresAddonController InitController()
    {
        if (thisScript != null) return thisScript;

        AntaresAddonController aac = GameObject.FindObjectOfType(typeof(AntaresAddonController)) as AntaresAddonController;
        if (aac != null) thisScript = aac;
        else
        {
            GameObject go = new GameObject("AntaresController");
            AntaresAddonController.thisScript = go.AddComponent<AntaresAddonController>();
            GetMultiTagsCollector();
        }
        return AntaresAddonController.thisScript;
    }

    public static void AddMultitagToObject(GameObject obj, params string[] mtags)
    {
        if (multitagedObjects == null) multitagedObjects = new Dictionary<string, List<GameObject>>();
        AntaresAddon addon = obj.GetComponent<AntaresAddon>();
        if (addon == null) addon = obj.AddComponent<AntaresAddon>();
        int count = mtags.Length;
        for (int i = 0; i < count; i++)
        {
            if (mtags[i] == "No Tags Found") continue;
            addon.MultitagAdd(mtags[i]);
            if (multitagedObjects.ContainsKey(mtags[i]))
            {
                List<GameObject> gm = multitagedObjects[mtags[i]];
                if (!gm.Contains(obj))
                {
                    gm.Add(obj);
                    multitagedObjects[mtags[i]] = gm;
                }
            }
            else
            {
                List<GameObject> go = new List<GameObject>();
                go.Add(obj);
                multitagedObjects.Add(mtags[i], go);
            }
        }
    }

    public static void AddMultitagToObject(Transform obj, params string[] mtags)
    {
        AddMultitagToObject(obj.gameObject, mtags);
    }

    public static void RemoveMultitagFromObject(GameObject obj, params string[] mtags)
    {
        if (multitagedObjects == null)
        {
            multitagedObjects = new Dictionary<string, List<GameObject>>();
            return;
        }
        AntaresAddon addon = obj.GetComponent<AntaresAddon>();
        if (addon == null) return;

        int count = mtags.Length;
        for (int i = 0; i < count; i++)
        {
            if (multitagedObjects.ContainsKey(mtags[i]))
            {
                List<GameObject> gm = multitagedObjects[mtags[i]];
                if (gm.Contains(obj))
                {
                    addon.MultitagRemove(mtags[i]);
                    gm.Remove(obj);
                    multitagedObjects[mtags[i]] = gm;
                }
            }
        }
    }

    public static void RemoveMultitagFromObject(Transform obj, params string[] mtags)
    {
        RemoveMultitagFromObject(obj.gameObject, mtags);
    }

    public static bool ObjectHasMultitag(GameObject obj, string multitag)
    {
        if (multitagedObjects == null)
        {
            multitagedObjects = new Dictionary<string, List<GameObject>>();
            return false;
        }
        if (!multitagedObjects.ContainsKey(multitag)) return false;
        return multitagedObjects[multitag].Contains(obj);
    }

    public static bool ObjectHasMultitag(Transform obj, string multitag)
    {
        return ObjectHasMultitag(obj.gameObject, multitag);
    }

    public static bool ObjectHasMultitagsBoth(GameObject obj, params string[] multitags)
    {
        int count = multitags.Length;
        for (int i = 0; i < count; i++) if (!ObjectHasMultitag(obj, multitags[i])) return false;
        return true;
    }

    public static bool ObjectHasMultitagsBoth(Transform obj, params string[] multitags)
    {
        return ObjectHasMultitagsBoth(obj.gameObject, multitags);
    }

    public static bool ObjectHasMultitagsAny(GameObject obj, params string[] multitags)
    {
        int count = multitags.Length;
        for (int i = 0; i < count; i++) if (ObjectHasMultitag(obj, multitags[i])) return true;
        return false;
    }

    public static bool ObjectHasMultitagsAny(Transform obj, params string[] multitags)
    {
        return ObjectHasMultitagsAny(obj.gameObject, multitags);
    }

    public static int ObjectsMultitagsCount(GameObject obj)
    {
        AntaresAddon addon = obj.GetComponent<AntaresAddon>();
        if (addon == null) return 0;
        return addon.MultitagsCount();
    }

    public static int ObjectsMultitagsCount(Transform obj)
    {
        return ObjectsMultitagsCount(obj.gameObject);
    }

    public static void RemoveAllMultitagsFromObject(GameObject obj)
    {
        AntaresAddon addon = obj.GetComponent<AntaresAddon>();
        if (addon == null) return;
        RemoveMultitagFromObject(obj, addon.GetMultitagsList());
    }

    public static void RemoveAllMultitagsFromObject(Transform obj)
    {
        RemoveAllMultitagsFromObject(obj.gameObject);
    }

    public static void OnObjectWithMultitagDisabled(GameObject obj)
    {
        AntaresAddon addon = obj.GetComponent<AntaresAddon>();
        if (addon == null) return;
        string[] mtags = addon.GetMultitagsList();
        int count = mtags.Length;
        for (int i = 0; i < count; i++)
        {
            if (multitagedObjects.ContainsKey(mtags[i]))
            {
                List<GameObject> gm = multitagedObjects[mtags[i]];
                if (gm.Contains(obj))
                {
                    gm.Remove(obj);
                    multitagedObjects[mtags[i]] = gm;
                }
            }
        }
    }

    public static GameObject GetMultitagObject(GameObject obj, string multitag)
    {
        AntaresAddon addon = obj.GetComponent<AntaresAddon>();
        if (addon == null) return null;
        return addon.GetMultitagObject(multitag);
    }

    public static GameObject GetMultitagObject(Transform obj, string multitag)
    {
        return GetMultitagObject(obj.gameObject, multitag);
    }

    public static List<GameObject> FindObjectsFithMultitag(string multitag)
    {
        List<GameObject> go = null;
        multitagedObjects.TryGetValue(multitag, out go);
        return go;
    }

    void Start()
    {
        DontDestroyOnLoad(this);
    }

    /// <summary>
    /// System method. Do not use it
    /// </summary>
    /// <returns></returns>
    public static Transform GetMultiTagsCollector()
    {
        if (thisScript == null) thisScript = GameObject.FindObjectOfType(typeof(AntaresAddonController)) as AntaresAddonController;
        foreach (Transform tr in thisScript.gameObject.GetComponentsInChildren<Transform>())
            if (tr.gameObject.name == "MultiTagsCollector")
            {
                thisScript.mTagsCollector = tr.gameObject;
                break;
            }
        if (thisScript.mTagsCollector == null)
        {
            thisScript.mTagsCollector = new GameObject("MultiTagsCollector");
            thisScript.mTagsCollector.transform.parent = thisScript.transform;
        }
        return thisScript.mTagsCollector.transform;
    }

    void OnLevelWasLoaded()
    {
        AntaresAddonController[] controllers = GameObject.FindObjectsOfType(typeof(AntaresAddonController)) as AntaresAddonController[];
        if (controllers.Length == 1) return;
        AntaresAddonController sceneAc = null;
        foreach (AntaresAddonController ac in controllers)
            if (ac == this)
            {
                sceneAc = ac;
                if (mTagsCollector == null) mTagsCollector = transform.Find("MultiTagsCollector").gameObject;
                if (mTagsCollector != null)
                {
                    foreach (Transform ch in mTagsCollector.gameObject.GetComponentsInChildren<Transform>())
                        ch.parent = sceneAc.mTagsCollector.transform;
                    foreach (AntaresAddon a_d in GameObject.FindObjectsOfType(typeof(AntaresAddon)) as AntaresAddon[])
                        a_d.multitagHolder = sceneAc.mTagsCollector;
                    AntaresAddonController.thisScript = sceneAc;
                }
            }
            else Destroy(ac.gameObject);
    }

    public static bool FreeMemoryOnPlay()
    {
        if (!thisScript) AntaresAddonController.InitController();
        return thisScript.freeMemoryOnPlay;
    }

    /// <summary>
    /// System method. Do not use it
    /// </summary>
    /// <returns></returns>
    public static int GetDescCount()
    {
        if (!thisScript) AntaresAddonController.InitController();
        return thisScript.maxDescLinesCount;
    }
}

