using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using UnityEngine.UI;
using static SOMDocManager;

public class PopupBehavior : MonoBehaviour
{

    [SerializeField] GameObject canvas;
    [SerializeField] Button CloseButton;
    [SerializeField] TMP_Text message;

    private Scroll activeScroll;
    private List<GameObject> parameterDisplays;

    public string ServerErrorMessage = "unknown server error";
    public string NonTotalMessage = "Scroll application not complete";
    public string UnknownErrorMessage = "Unkown error - did you apply all facts?";
    public string InvalidAssignmentMessage = "Invalid Assignment";

    private string errorMessage = "";
    // Start is called before the first frame update
    void Awake()
    {
        CommunicationEvents.PushoutFactFailEvent.AddListener(onFailedScrollInput);

        CloseButton.onClick.RemoveAllListeners();
        CloseButton.onClick.AddListener(hidePopUp);
    }

    public void setMessage(string errorMessage)
    {
        this.message.text = errorMessage;
    }

    public void setScroll(Scroll scroll)
    {
        this.activeScroll = scroll;
    }
    public void setParameterDisplays(List<GameObject> parameters)
    {
        this.parameterDisplays = parameters;
    }

    public void showPopUp()
    {
        canvas.SetActive(true);
        StartCoroutine(hideAfter5sec());
    }

    private IEnumerator hideAfter5sec()
    {
        yield return new WaitForSeconds(5);
        hidePopUp();
    }

    public void hidePopUp()
    {
        canvas.SetActive(false);
    }

    /// <summary>
    /// this method creates a helpful error message and shows the popup. For it to work properly, the setScroll and setParameterDisplays must have been set.
    /// </summary>
    /// <param name="startfact"></param>
    /// <param name="errorInfo"></param>
    public void onFailedScrollInput(Fact startfact, Scroll.ScrollApplicationInfo errorInfo)
    {
        setMessage(generateHelpfulMessageAndAnimateScrollParam(errorInfo));
        showPopUp();
    }

    private string generateHelpfulMessageAndAnimateScrollParam(Scroll.ScrollApplicationInfo errorInfo)
    {
        if(errorInfo == null)
        {
            return ServerErrorMessage;
        }
        int invAssCount = 0;
        errorMessage = "";
        for (int i = 0; i < errorInfo.errors.Length; i++) { 
            Scroll.ScrollApplicationCheckingError error = errorInfo.errors[i];
            
            //check which error ocurred and set Message to a helpful error message.
            if (error.kind == "nonTotal")
            {
                errorMessage += NonTotalMessage;
                errorMessage += '\n';
            } else if (error.kind == "invalidAssignment")
            {
                invAssCount++;
                Scroll.ScrollFact fact = parseFactFromError(error);

                //animate all invalidly assigned facts
                if (parameterDisplays != null && fact != null)
                {
                    foreach (GameObject g in parameterDisplays)
                    {
                        RenderedScrollFact scrollfact = g.transform.GetChild(0).GetComponent<RenderedScrollFact>();
                        if (scrollfact.factUri == fact.@ref.uri)
                        {
                            scrollfact.ScrollParameterObject.GetComponentInChildren<ImageHintAnimation>().AnimationTrigger();
                        }
                    }
                } else
                {
                    Debug.Log("PopupBehavior: Error: scroll or parameterDisplays not set.");
                }
            } else if (error.kind == "unknown")
            {
                errorMessage += UnknownErrorMessage;
                errorMessage += '\n';
            }
        }

        //invalid assignment message
        if(invAssCount > 0)
        {
            errorMessage += invAssCount.ToString() + " " + InvalidAssignmentMessage;
            if(invAssCount > 1) //plural for invalid assignments
            {
                errorMessage += 's';
            }
            errorMessage += '\n';
        }

        return errorMessage;
    }

    //this should be changed, the Fact Object should be parsed by JSON. This is a workaround because the MMT servers JSON serialization contains a bug
    private Scroll.ScrollFact parseFactFromError(Scroll.ScrollApplicationCheckingError error)
    {
        if(error == null || error.msg == null)
        {
            return null;
        }
        string message = error.msg;

        //cut start of string
        int indexFact = message.IndexOf('[');
        string factUri = message.Substring(indexFact + 1);

        // cut end of string
        int indexFactEnd = factUri.IndexOf(']');
        string rest = factUri.Substring(indexFactEnd);
        factUri = factUri.Substring(0, indexFactEnd);

        //get fact Label from the rest of the string
        int factNameLength = rest.IndexOf('?') - 2;
        string factLabel = rest.Substring(2, factNameLength);

        //add ?factName to URI
        factUri += "?" + factLabel;

        //find the required fact in the active scroll thats invalidly assigned
        if((activeScroll == null))
        {
            return null;
        }
        foreach (Scroll.ScrollFact f in activeScroll.requiredFacts)
        {
            if (f.@ref.uri.Equals(factUri))
            {
                return f;
            }
        }
        return null;
    }
}