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

public class Outfitter : MonoBehaviour {

    // Stores a list of all weapons available to character
    [SerializeField]
    private List<WeaponKit> WeaponsKit;


    [SerializeField]
    private WeaponStates _CurrentWeapon;

    // stores the old weapon state of the character
    private WeaponStates CurrentWeapon
    {
        get { return _CurrentWeapon; }
        set { _CurrentWeapon = value; }
    }

    // stores the index number where each weaponstate can be found in the list for easy retrieval
    private Dictionary<WeaponStates, int> weaponKitIndexes;

    private Dictionary<WeaponStates, List<Renderer>> weapons;

    private Animator animator;

    private void Awake()
    {
        // Register to listen for WEAPON_STATE_CHANGED event.
        Messenger<WeaponStates, string>.AddListener(GameEvent.WEAPON_STATE_CHANGED, OnWeaponStateChanged);
    }

    private void OnDestroy()
    {
        // Stop listening for WEAPON_STATE_CHANGED event as game object has been destroyed.
        Messenger<WeaponStates, string>.RemoveListener(GameEvent.WEAPON_STATE_CHANGED, OnWeaponStateChanged);
    }

    
    // Use this for initialization
    void Start () {
        animator = GetComponent<Animator>();

        LoadWeapons();
        // oldWeaponState = CurrentWeapon;
    }


    private void LoadWeapons()
    {
        // Initialise a new dictionary ready to store the weapons for each weapon state
        weapons = new Dictionary<WeaponStates, List<Renderer>>();

        // Get all the renderers attached to this game object
        Renderer[] gameObjectRenderers = GetComponentsInChildren<Renderer>(true);

        // Loop through each of the renderers attached to this game object
        foreach (Renderer renderer in gameObjectRenderers)
        {
            // Loop through each of the weapon kit states set up for this character
            foreach (WeaponKit weaponKit in WeaponsKit)
            {
                // Add a new reference key for this weapon state if it does not already exist
                if (!weapons.ContainsKey(weaponKit.WeaponState))
                {
                    weapons.Add(weaponKit.WeaponState, new List<Renderer>());
                }

                // Loop through all of the weapons defined for this state
                foreach (Renderer weaponMaterial in weaponKit.Weapons)
                {
                    // Check if this is a recognised material for this game object
                    //Debug.Log(weaponMaterial.name);
                    //Debug.Log(renderer.name);
                    if (weaponMaterial.name == renderer.name)
                    {
                        // If this is the current weapon state, enable the material, otherwise disable it
                        if (CurrentWeapon == weaponKit.WeaponState)
                        {
                            renderer.enabled = true;
                        } else
                        {
                            renderer.enabled = false;
                        }
                        
                        weapons[weaponKit.WeaponState].Add(renderer);
                    }
                }
            }
        }
    }



    // Update is called once per frame
    void Update () {
        
    }

    private List<Renderer> GetWeapons(WeaponStates weaponState)
    {
        // Check if the dictionary key exists and if yes, return the list of weapon materials for this weapon state, otherwise return null
        if (weapons.ContainsKey(weaponState))
        {
            return weapons[weaponState];
        }
        else
        {
            return null;
        }
    }


    private void OnWeaponStateChanged(WeaponStates newWeaponState, string character)
    {
        // Check that this is the game object that triggered the event that is responding
        if (gameObject.name != character)
        {
            return; // not, exit and return early
        }
        

        if (CurrentWeapon == newWeaponState)
        {
            return;
        }

        // Retrieve the character's previous weapon state
        List<Renderer> oldWeapons = GetWeapons(CurrentWeapon);
        // Disable all the weapons previously carried.
        if (oldWeapons != null)
        {
            foreach (Renderer renderer in oldWeapons)
            {
                renderer.enabled = false;
            }
        }

        // Retrieve the character's new weapon state
        List<Renderer> newWeapons = GetWeapons(newWeaponState);
        

        // Enable all the weapons now being carried
        if (newWeapons != null)
        {
            foreach (Renderer renderer in newWeapons)
            {
                renderer.enabled = true;
            }
        }

        // Update the old weapon state to the changed weapon state
        CurrentWeapon = newWeaponState;
        
        // Update the animator's weapon state so that it can play the corresponding animation
        animator.SetInteger("WeaponState", (int)newWeaponState);
        Messenger<WeaponStates, string>.Broadcast(GameEvent.WEAPON_STATE_CHANGE_COMPLETED, newWeaponState, character);
    }

    public Transform[] GetCurrentWeapons()
    {
        // Initialise new list to store the weapon game objects
        List<Transform> weapons = new List<Transform>();

        // Get the current weapons character is kitted with
        List<Renderer> currentWeapons = GetWeapons(CurrentWeapon);

        // Check that character has weapons
        if (currentWeapons != null)
        {
            // Loop through each weapon materials and add the game object to the list to return
            foreach (Renderer renderer in currentWeapons)
            {
                weapons.Add(renderer.gameObject.transform);
            }
        }

        // Return the found weapons as an array
        return weapons.ToArray();
    }    
}
