using System;
using System.Collections;
using System.Linq;
using System.Collections.Generic;
using UnityEngine;
using Sirenix.OdinInspector;
using KairoEngine.Core;

namespace KairoEngine.Core.GameActions
{

    [System.Serializable, HideReferenceObjectPicker]
    public class GameObjectControllerGameAction : GameActionBase
    {
        public enum ControllerAction
        {
            Enable,
            Disable,
            Destroy
        }

        public enum TargeVariableType
        {
            Direct,
            Variable
        }

        public override string name 
        { 
            get
            {
                return $"{action.ToString()} {GetObjName(target)}"; 
            }
        }

        public override GameActionsController controller { 
            get => _controller; 
            set 
            {
                _controller = value;
                typeName = "GameObjectControllerGameAction";
                className =  this.GetType().AssemblyQualifiedName;
                GetCompatibleVariablenames();
            }
        }
        public override string GetTypeName() => "GameObjectControllerGameAction";
        public override string GetActionName() => "Core/GameObject Controller";

        [IconFoldoutGroup("@name", "Assets/Plugins/KairoEngine/Core/Editor/Icons/InstantiateGameActionIcon.png")]
        public ControllerAction action = ControllerAction.Enable;

        [IconFoldoutGroup("@name")] 
        public TargeVariableType targetType;

        [IconFoldoutGroup("@name"), ShowIf("@targetType == TargeVariableType.Direct"), NonSerialized, ShowInInspector] 
        public GameObject target;

        [IconFoldoutGroup("@name"), ShowIf("@targetType == TargeVariableType.Variable"),ValueDropdown("possibleVariables", IsUniqueList = false)]
        public string targetVariable;

        private IEnumerable possibleVariables = new ValueDropdownList<string>();

        public GameObjectControllerGameAction(GameActionsController controller) : base(controller)
        {
            this.controller = controller;
            className =  this.GetType().AssemblyQualifiedName;
        }

        private string GetObjName(GameObject obj)
        {
            if(obj == null) return "NULL";
            else return $"\'{obj.name}\'";
        }

        public override void Start()
        {
            GameObject obj;
            if(targetType == TargeVariableType.Direct) obj = target;
            else obj = GetVariable<GameObject>(targetVariable, null);
            if(obj != null)
            {
                switch (action)
                {
                    case ControllerAction.Enable:
                        obj.SetActive(true);
                        break;
                    case ControllerAction.Disable:
                        obj.SetActive(false);
                        break;
                    case ControllerAction.Destroy:
                        GameObject.Destroy(obj);
                        break;
                    default:
                        break;
                }
            }
            _done = true;
            _started = true;
        }

        public override void Update() { }

        public override void Restart()
        {
            _done = false;
            _started = false;
        }

        private void GetCompatibleVariablenames()
        {
            if(_controller == null) return;
            if(_controller.context == null) return;
            possibleVariables = _controller.context.variables
                .Where(x => x.GetTypeName() is "GameActionContextGameObject")
                .Select(x => new ValueDropdownItem(x.name, x.name)); 
        }

        public static GameObjectControllerGameAction JSONToGameObjectControllerGameAction(string data)
        {
            return JsonUtility.FromJson<GameObjectControllerGameAction>(data);
        }

        private GameObjectControllerGameAction Duplicate(GameActionsController controller)
        {
            GameObjectControllerGameAction action = new GameObjectControllerGameAction(controller == null ? this.controller : controller);
            action.controller = controller;
            return action;
        }

        private T GetVariable<T>(string title, T defaultValue)
        {
            for (int i = 0; i < controller.context.variables.Count; i++)
            {
                if(controller.context.variables[i].name == title)
                {
                    return controller.context.variables[i].GetValue<T>(defaultValue);
                }
            }
            return defaultValue;
        }

        public override void OnBeforeSerialize(GameActionObjectSerializer serializer, int n, int depth) 
        { 
            serializer.SerializeGameObject($"{depth}-{n}-Prefab", target);
        }
        public override void OnBeforeDeserialize(GameActionObjectSerializer serializer, int n, int depth) 
        { 
            target = serializer.DeserializeGameObject($"{depth}-{n}-Prefab");
        }
    }
}