Skip to content
Snippets Groups Projects
ScrollDetails.cs 12.08 KiB
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using UnityEngine.Networking;
using Newtonsoft.Json;
using static CommunicationEvents;
using System.Linq;
using static SOMDocManager;

public class ScrollDetails : MonoBehaviour
{
    public WorldCursor cursor;
    public GameObject parameterDisplayPrefab;
    public Scroll ActiveScroll;
    public GameObject mmtAnswerPopUp;

    public static List<GameObject> ParameterDisplays;
    private static List<Scroll.ScrollAssignment> LatestCompletions;
    private static List<Fact> LatestRenderedHints;

    public string currentMmtAnswer;

    public bool dynamicScrollDescriptionsActive = true;
    public bool automaticHintGenerationActive = true;

    // Start is called before the first frame update
    void Start()
    {
        cursor ??= GameObject.FindObjectOfType<WorldCursor>();
        
        mmtAnswerPopUp.GetComponent<PopupBehavior>().hidePopUp();
    }

    private void OnEnable()
    {
        ScrollFactHintEvent.AddListener(animateHint);
        NewAssignmentEvent.AddListener(newAssignmentTrigger);
        RemoveFactEvent.AddListener(removeFactFromAssignment);
    }

    private void OnDisable()
    {
        ScrollFactHintEvent.RemoveListener(animateHint);
        NewAssignmentEvent.RemoveListener(newAssignmentTrigger);
        RemoveFactEvent.RemoveListener(removeFactFromAssignment);
    }

    public void setScroll(Scroll s)
    {
        Transform originalScroll = gameObject.transform.GetChild(1).transform;
        Transform originalScrollView = originalScroll.GetChild(1);
        Transform originalViewport = originalScrollView.GetChild(0);
        this.ActiveScroll = s;

        originalScroll.GetChild(0).GetComponent<TextMeshProUGUI>().text = s.description;

        //Clear all current ScrollFacts
        originalViewport.GetChild(0).gameObject.DestroyAllChildren();

        ParameterDisplays = new List<GameObject>();
        for (int i = 0; i < s.requiredFacts.Count; i++)
        {
            var originalObj = Instantiate(parameterDisplayPrefab, Vector3.zero, Quaternion.identity, transform);
            var originalScrollFact = originalObj.transform.GetChild(0).GetComponent<RenderedScrollFact>();
            originalScrollFact.ID = i;
            originalScrollFact.Label = s.requiredFacts[i].label;
            originalScrollFact.factUri = s.requiredFacts[i].@ref.uri;

            originalObj.transform.SetParent(originalViewport.GetChild(0));

            ParameterDisplays.Add(originalObj);
        }

        //set active scroll for ErrorMessagePopup
        PopupBehavior popup = mmtAnswerPopUp.GetComponent<PopupBehavior>();
        popup.setScroll(this.ActiveScroll);
        popup.setParameterDisplays(ParameterDisplays);
    }

    public void magicButtonTrigger()
    {
        StartCoroutine(magicButton());

        IEnumerator magicButton()
        {
            //Non blocking wait till sendView() is finished
            yield return sendView("/scroll/apply");
            if (currentMmtAnswer == null)
            {
                Debug.Log("DAS HAT NICHT GEKLAPPT");
                PushoutFactFailEvent.Invoke(null, null);
            }
            else
            {
                Debug.Log(currentMmtAnswer);
                Scroll.ScrollApplicationInfo pushout = JsonConvert.DeserializeObject<Scroll.ScrollApplicationInfo>(currentMmtAnswer);
                if (pushout.acquiredFacts.Count == 0)
                    PushoutFactFailEvent.Invoke(null, pushout);
                readPushout(pushout.acquiredFacts);
            }
        }
    }

    public void newAssignmentTrigger()
    {
        if (this.automaticHintGenerationActive || this.dynamicScrollDescriptionsActive)
            StartCoroutine(newAssignment());

        IEnumerator newAssignment()
        {
            //Non blocking wait till sendView() is finished
            yield return sendView("/scroll/dynamic");

            if (currentMmtAnswer == null)
            {
                Debug.Log("DAS HAT NICHT GEKLAPPT");
            }
            else
            {
                // Todo delte maybe
                Debug.Log("Current mmt answer:  " + currentMmtAnswer);
                Scroll.ScrollDynamicInfo scrollDynamicInfo = JsonConvert.DeserializeObject<Scroll.ScrollDynamicInfo>(currentMmtAnswer);
                processScrollDynamicInfo(scrollDynamicInfo);
            }
        }
    }

    IEnumerator sendView(string endpoint)
    {
        string body = prepareScrollAssignments();
        System.DateTime startTime = System.DateTime.UtcNow;

        using UnityWebRequest www = UnityWebRequest.Put(ServerAdress + endpoint, body);
        www.method = UnityWebRequest.kHttpVerbPOST;
        www.SetRequestHeader("Content-Type", "application/json");
        yield return www.SendWebRequest();

        System.DateTime twoTime = System.DateTime.UtcNow;
        if (www.result == UnityWebRequest.Result.ConnectionError
         || www.result == UnityWebRequest.Result.ProtocolError)
        {
            Debug.Log(www.error);
            currentMmtAnswer = null;
        }
        else
        {
            string answer = www.downloadHandler.text;
            currentMmtAnswer = answer;
        }
        System.DateTime endTime = System.DateTime.UtcNow;

        string diffInSeconds = (endTime - startTime).TotalMilliseconds.ToString();
        string diff = (twoTime - startTime).TotalMilliseconds.ToString();
    }

    private string prepareScrollAssignments()
    {
        List<Scroll.ScrollAssignment> assignmentList = new();

        for (int i = 0; i < ParameterDisplays.Count; i++)
        {
            Fact tempFact = ParameterDisplays[i].GetComponentInChildren<DropHandling>().currentFact;
            if (tempFact != null)
                assignmentList.Add(new Scroll.ScrollAssignment(ActiveScroll.requiredFacts[i].@ref.uri, tempFact.Id));
        }

        return JsonConvert.SerializeObject(new Scroll.FilledScroll(ActiveScroll.@ref, assignmentList));
    }

    private void readPushout(List<MMTDeclaration> pushoutFacts)
    {
        mmtAnswerPopUp.GetComponent<PopupBehavior>().hidePopUp(); //close error Window

        bool samestep = false;
        for (int i = 0; i < pushoutFacts.Count; i++, samestep = true)
        {
            Fact newFact = ParsingDictionary.parseFactDictionary[pushoutFacts[i].getType()].Invoke(pushoutFacts[i]);
            if (newFact != null)
                PushoutFactEvent.Invoke(FactManager.AddFactIfNotFound(newFact, out _, samestep, null, ActiveScroll.label), FactObject.FactMaterials.Solution);
         
            else
                Debug.Log("Parsing on pushout-fact returned null -> One of the dependent facts does not exist");
        }
    }

    public void processScrollDynamicInfo(Scroll.ScrollDynamicInfo scrollDynamicInfo)
    {
        LatestCompletions = scrollDynamicInfo.completions.Count > 0 
            ? scrollDynamicInfo.completions[0] 
            : new List<Scroll.ScrollAssignment>();


        List<string> hintUris = LatestCompletions.Select(completion => completion.fact.uri).ToList();

        //Update Scroll, process data for later hints and update Uri-List for which hints are available
        hintUris = processRenderedScroll(scrollDynamicInfo.rendered, hintUris);

        if (automaticHintGenerationActive)
            //Show that Hint is available for ScrollParameter
            HintAvailableEvent.Invoke(hintUris);
    }

    public List<string> processRenderedScroll(Scroll rendered, List<string> hintUris)
    {
        Transform scroll = gameObject.transform.GetChild(1).transform;

        if (this.dynamicScrollDescriptionsActive)
            //Update scroll-description
            scroll.GetChild(0).GetComponent<TextMeshProUGUI>().text = rendered.description;

        LatestRenderedHints = new List<Fact>();
        for (int i = 0; i < rendered.requiredFacts.Count; i++)
        {
            GameObject obj = ParameterDisplays.Find(x => x.transform.GetChild(0).GetComponent<RenderedScrollFact>().factUri.Equals(rendered.requiredFacts[i].@ref.uri));

            if (this.dynamicScrollDescriptionsActive)
            {
                //Update ScrollParameter label
                obj.transform.GetChild(0).GetComponent<RenderedScrollFact>().Label = rendered.requiredFacts[i].label;
            }

            //Check Hint Informations
            //If ScrollFact is assigned -> No Hint
            if (obj.transform.GetChild(0).GetComponent<DropHandling>().currentFact == null)
            {

                //  Debug.Log(" print out " + rendered.requiredFacts[i].getType());
                Fact currentFact = ParsingDictionary.parseFactDictionary[rendered.requiredFacts[i].getType()].Invoke(rendered.requiredFacts[i]);
                //If currentFact could be parsed: this fact maybe not yet exists in the global fact-list but there must be a fact
                // of the same type and the same dependent facts in the fact-list, otherwise currentFact could not have been parsed

                //If the fact could not be parsed -> Therefore not all dependent Facts exist -> No Hint
                //AND if fact has no dependent facts -> No Hint
                if (currentFact != null && currentFact.HasDependentFacts)
                {
                    //Hint available for abstract-problem uri
                    hintUris.Add(currentFact.Id);
                    LatestRenderedHints.Add(currentFact);
                }
            }
        }

        return hintUris;
    }

    public void animateHint(GameObject scrollParameter, string scrollParameterUri)
    {
        Scroll.ScrollAssignment suitableCompletion = LatestCompletions.Find(x => x.fact.uri.Equals(scrollParameterUri));
        Fact fact;

        if (suitableCompletion != null)
        {
            if (FactOrganizer.AllFacts.ContainsKey(suitableCompletion.assignment.uri))
            {
                fact = FactOrganizer.AllFacts[suitableCompletion.assignment.uri];
                //Animate ScrollParameter
                scrollParameter.GetComponentInChildren<ImageHintAnimation>().AnimationTrigger();
                //Animate Fact in FactPanel
                AnimateExistingFactEvent.Invoke(fact, FactObject.FactMaterials.Hint);
            }
        }
        else if (LatestRenderedHints.Exists(x => x.Id.Equals(scrollParameterUri)))
        {
            fact = LatestRenderedHints.Find(x => x.Id.Equals(scrollParameterUri));
            var factId = fact.Id;

            //If there is an equal existing fact -> Animate that fact AND ScrollParameter
            if (FactOrganizer.AllFacts.ContainsKey(factId))
            {
                Fact existingFact = FactOrganizer.AllFacts[factId];

                //Animate ScrollParameter
                scrollParameter.GetComponentInChildren<ImageHintAnimation>().AnimationTrigger();
                //Animate Fact in FactPanel
                AnimateExistingFactEvent.Invoke(existingFact, FactObject.FactMaterials.Hint);
            }
            //If not -> Generate a Fact-Representation with such dependent facts
            else
            {
                //Animate ScrollParameter
                scrollParameter.GetComponentInChildren<ImageHintAnimation>().AnimationTrigger();
                //Generate new FactRepresentation and animate it
                AnimateNonExistingFactEvent.Invoke(fact);
            }
        }
    }

    //this is called whenever a Fact is Deleted in the world, to make sure it is removed from the scroll
    public void removeFactFromAssignment(Fact fact)
    {
        Transform originalScroll = gameObject.transform.GetChild(1).transform;
        Transform originalScrollView = originalScroll.GetChild(1);
        Transform originalViewport = originalScrollView.GetChild(0);

        for (int i = 0; i < originalViewport.GetChild(0).childCount; i++)
        {
            RenderedScrollFact scrollFact = originalViewport.GetChild(0).transform.GetChild(i).GetChild(0).gameObject.GetComponent<RenderedScrollFact>();
            if (scrollFact.Label == fact.Label)
            {
                DropHandling dropHandling = originalViewport.GetChild(0).transform.GetChild(i).GetChild(0).gameObject.GetComponent<DropHandling>();
                dropHandling.OnPointerClick(null);
            }
        }
    }
}