//============= Copyright (c) Ludic GmbH, All rights reserved. ==============
//
// Purpose: Part of the My Behaviour Tree Controller Code
//
//=============================================================================


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

#if UNITY_EDITOR
using UnityEditor;
[CustomEditor(typeof(ComponentHandler))]
public class ComponentHandlerInspector : Editor {
    public override void OnInspectorGUI() {
        ComponentHandler myTarget = (ComponentHandler)target;
        GUILayout.TextArea("Check the ComponentController");
        myTarget.hideFlags = HideFlags.HideInInspector;
    }

    public virtual void OnCustomInspectorGUI () {
        ComponentHandler myTarget = (ComponentHandler)target;
        if (!string.IsNullOrEmpty(myTarget.titleText)) {
            EditorGUILayout.BeginHorizontal();
            GUILayout.Label($"{myTarget.titleText} functions", GUILayout.MinWidth(200));
            myTarget.showHelpText = EditorGUILayout.Toggle(myTarget.showHelpText, GUILayout.Width(20));
            EditorGUILayout.EndHorizontal();
            // 
        }
        // EditorGUILayout.BeginHorizontal();
        // if (myTarget.helpText != null) {
        //     myTarget.showHelpText = EditorGUILayout.ToggleLeft("Show Info", myTarget.showHelpText);
        // }
        // EditorGUILayout.Space();
        // EditorGUILayout.Space();
        // EditorGUILayout.EndHorizontal();
        EditorGUILayout.BeginHorizontal();
        if (myTarget.showHelpText) {
            if (myTarget.helpText != null) {
                // string[][] helpTextSplit = myTarget.helpText;
                for (int i=0; i<myTarget.helpText.Length; i++) {
                    if (GUILayout.Button(new GUIContent($"{myTarget.helpText[i][0]} Command", myTarget.helpText[i][1]), GUILayout.MaxWidth(140))) {
                        EditorGUIUtility.systemCopyBuffer = myTarget.helpText[i][2];
                    }
                    if (((i+1)%3)==0) {
                        EditorGUILayout.EndHorizontal();
                        EditorGUILayout.BeginHorizontal();
                    }
                }
            }
        }
        EditorGUILayout.EndHorizontal();
        EditorGUILayout.Space();
        DrawDefaultInspector();
        if (GUILayout.Button($"Remove {myTarget.GetType()}")) {
            DestroyImmediate(myTarget);
        }
    }
}
#endif

[RequireComponent(typeof(ComponentController))]
public class ComponentHandler : MonoBehaviour {
    public virtual string TypeLabel () {
        return "CMP";
    }

    public virtual string ContentLabel () {
        return "undefined";
    }

    public virtual void UpdateComponent() {
    }

    public virtual void Start () {
    }

    public virtual void Update () {
        // UpdateAlpha();
    }

    [HideInInspector]
    public bool showHelpText = false;

    public virtual string titleText {
        get {
            return null;
        }
    }
    
    public virtual string[][] helpText {
        get {
            return null;
        }
    }

    public string roomId {
        get {
            return GetComponent<ComponentController>().roomId;
        }
    }

    public virtual void Run (MyBT.NodeState nodeState) {
        if (Task.isDebugging) {
            Debug.LogWarning($"ComponentHandler.Run: not implemented for {this.GetType()}");
        }
    }

    public virtual void Abort (MyBT.NodeState nodeState) {
        if (Task.isDebugging) {
            Debug.LogWarning($"ComponentHandler.Abort: not implemented for {this.GetType()}");
        }
    }

    public virtual bool IsRunning (MyBT.NodeState nodeState) {
        if (Task.isDebugging) {
            Debug.LogWarning($"ComponentHandler.IsRunning: not implemented for {this.GetType()}");
        }
        return false;
    }

    public virtual void Show (MyBT.NodeState nodeState) {
        // Debug.LogWarning($"ComponentHandler.ShowNow: not implemented for {this.GetType()}");
        if ((nodeState == NodeState.FirstRun) || (nodeState == NodeState.Running))  {
            sourceAlpha = shown;
            targetAlpha = shown;
            timeSum = 1;

            SetAlpha(targetAlpha);

            Task.SetSucceeded();
        }
    }

    public virtual void Hide (MyBT.NodeState nodeState) {
        // Debug.LogWarning($"ComponentHandler.HideNow: not implemented for {this.GetType()}");
        if ((nodeState == NodeState.FirstRun) || (nodeState == NodeState.Running)) {
            sourceAlpha = hidden;
            targetAlpha = hidden;
            timeSum = 1;

            SetAlpha(targetAlpha);
            
            Task.SetSucceeded();
        }
    }

    public virtual void FadeIn (MyBT.NodeState nodeState) {
        // Debug.LogWarning($"ComponentHandler.FadeIn: not implemented for {this.GetType()}");
        if (nodeState == NodeState.FirstRun) {
            sourceAlpha = GetAlpha();
            targetAlpha = shown;
            fadeTime = fadeInTime;
            timeSum = -Time.deltaTime / fadeInTime;
        }
        if (nodeState == NodeState.Running) {
            UpdateAlpha();
        }
    }

    public virtual void FadeOut (MyBT.NodeState nodeState) {
        // Debug.LogWarning($"ComponentHandler.FadeOut: not implemented for {this.GetType()}");
        if (nodeState == NodeState.FirstRun) {
            sourceAlpha = GetAlpha();
            targetAlpha = hidden;
            fadeTime = fadeOutTime;
            timeSum = -Time.deltaTime / fadeOutTime;
        }
        if (nodeState == NodeState.Running) {
            UpdateAlpha();
        }
    }

    public virtual void Set (MyBT.NodeState nodeState, string key, string value) {
        if (Task.isDebugging) {
            Debug.LogWarning($"ComponentHandler.Set: not implemented for {this.GetType()}");
        }
        Task.SetError();
    }

    public virtual void SetFloat(MyBT.NodeState nodeState, string key, float value)
    {
        if (Task.isDebugging)
        {
            Debug.LogWarning($"ComponentHandler.SetFloat: not implemented for {this.GetType()}");
        }
        Task.SetError();
    }

    public virtual void Enable(MyBT.NodeState nodeState)
    {
        if (Task.isDebugging)
        {
            Debug.LogWarning($"ComponentHandler.Enable: not implemented for {this.GetType()}");
        }
    }

    public virtual void Disable(MyBT.NodeState nodeState)
    {
        if (Task.isDebugging)
        {
            Debug.LogWarning($"ComponentHandler.Disable: not implemented for {this.GetType()}");
        }
    }

    public virtual void SetPosition(MyBT.NodeState nodeState, float newX, float newY, float newZ)
    {
        if (Task.isDebugging)
        {
            Debug.LogWarning($"ComponentHandler.SetPosition: not implemented for {this.GetType()}");
        }
    }

    public virtual void AbortEventListener(MyBT.NodeState nodeState)
    {
        if (Task.isDebugging)
        {
            Debug.LogWarning($"ComponentHandler.AbortEventListener: not implemented for {this.GetType()}");
        }
    }

    public virtual void ListenToEvent(MyBT.NodeState nodeState)
    {
        if (Task.isDebugging)
        {
            Debug.LogWarning($"ComponentHandler.ListenToEvent: not implemented for {this.GetType()}");
        }
    }

    public virtual void StopSound(MyBT.NodeState nodeState)
    {
        if (Task.isDebugging)
        {
            Debug.LogWarning($"ComponentHandler.StopSound: not implemented for {this.GetType()}");
        }
    }

    protected float sourceAlpha;
    protected float targetAlpha;
    protected float timeSum;
    protected float fadeTime = 1f;
    protected float _prevCutOff = -1;

    protected float hidden = 1;
    protected float shown = 0;

    [HideAttributeinSubClass]
    public float fadeInTime = 1.5f;
    [HideAttributeinSubClass]
    public float fadeOutTime = 1.5f;

    private void UpdateAlpha() {
        if (timeSum < 1) {
            float diffColor = targetAlpha - GetAlpha();
            timeSum += Time.deltaTime / fadeTime;

            float alphaValue = Mathf.Lerp(sourceAlpha, targetAlpha, timeSum);
            SetAlpha(alphaValue);
        }
        // set final value
        else {
            SetAlpha(targetAlpha);
            Task.SetSucceeded();
        }
    }

    public virtual void SetAlpha(float alpha) {
        // Debug.LogWarning($"ComponentHandler.SetAlpha: not implemented for {this.GetType()} {alpha}");
    }

    public virtual float GetAlpha() {
        // Debug.LogWarning($"ComponentHandler.GetAlpha: not implemented for {this.GetType()}");
        return targetAlpha;
    }
}