using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using CSVReader;
namespace ObjectScripts
{
    public class EventHandler : AbstractEventHandler
    {

        ///<summary>
        /// EventPrefab
        ///</summary>
        [SerializeField] GameObject EventPrefab;
        ///<summary>
        /// Manager Object
        ///</summary>
        [SerializeField] AbstractManager Manager;
        ///<summary>
        /// next Id to assign
        ///</summary>     
        private uint nextID = 0;
        ///<summary>
        /// Event CSV Reader
        ///</summary>
        EventCSVReader EventCSV;
        ///<summary>
        /// EventBuffer
        ///</summary>
        EventObject[] Events;
        ///<summary>
        /// MapSensor for mapping local position to world position
        ///</summary>
        IMapSensor MapSensor;
        ///<summary>
        /// Control Coroutine
        ///</summary>
        bool running;
        ///<summary>
        /// number of known events
        ///</summary>
        float KnownCount = 0;
   
        void Start()
        {
            EventList = new List<AbstractEventScript>();
            // EventCSV = new EventCSVReader(filename);
            // EventObject[] events = EventCSV.ReadFile();
            // Handle(events);

        }
        ///<summary>
        /// Set up EventHandler
        ///</summary>
        public override void SetUp(EventCSVReader eventCSV, IMapSensor mapSensor)
        {
            EventCSV = eventCSV;
            MapSensor = mapSensor;
            running = true;
            StartCoroutine(UpdateWithProzessorUpdateRate());
        }
        ///<summary>
        /// Read events every 1/updaterate seconds 
        ///</summary>
        IEnumerator UpdateWithProzessorUpdateRate()
        {
            while (running)
            {
                this.Events = this.EventCSV.ReadFile();
                if (Events.Length > KnownCount)
                {
                    Events = MapEventsToWorldposition(Events);
                    Handle(Events);
                }

                yield return new WaitForSecondsRealtime(this.Manager.UpdateRateInSeconds);
            }

        }
        ///<summary>
        /// Map Event local position to global position
        ///</summary>
        private EventObject[] MapEventsToWorldposition(EventObject[] events)
        {
            List<InputObject> eventPositions = new List<InputObject>();
            List<InputObject> eventViewingPositions = new List<InputObject>();
            foreach (EventObject e in events)
            {
                eventPositions.Add(new InputObject(0, 0, e.Pos.x, e.Pos.y, e.Pos.z, 0, 0, 0, 0, 0, 0, 0, 0, 0, e.ID));

                eventViewingPositions.Add(new InputObject(0, 0, e.IdealViewingPos.x, e.IdealViewingPos.y, e.IdealViewingPos.z, 0, 0, 0, 0, 0, 0, 0, 0, 0, e.ID));
            }

            eventPositions = MapSensor.MapToWorldPositions(eventPositions);
            eventViewingPositions = MapSensor.MapToWorldPositions(eventViewingPositions);
            int len = eventPositions.Count;

            for (int i = 0; i < len; i++)
            {
                InputObject eventPosition = eventPositions[i];
                InputObject eventViewingPosition = eventViewingPositions[i];
                events[i].Pos = new Vector3(eventPosition.Pos.x, eventPosition.Pos.y, eventPosition.Pos.z);
                events[i].setIdealViewingPosition(eventViewingPosition.Pos.x, eventViewingPosition.Pos.y, eventViewingPosition.Pos.z);

            }
            return events;
        }
        ///<summary>
        /// Handle new events
        ///</summary>
        public override void Handle(EventObject[] events)
        {
            if (events.Length > EventList.Count)
                for (int i = EventList.Count; i < events.Length; i++)
                {
                    EventObject e = events[i];
                    createEvent(e);
                }
        }
        ///<summary>
        /// Create new Events
        ///</summary>
        void createEvent(EventObject e)
        {
            GameObject eventGameObject = Instantiate(EventPrefab);
            eventGameObject.name = "Event" + e.TimestampStart + " " + e.Type;
            AbstractEventScript eventScript = eventGameObject.GetComponent<AbstractEventScript>();
            eventScript.Camera = this.Camera;
            eventScript.Event = e;
            eventScript.EventHandler = this;
            eventScript.ID = nextID;
            nextID++;
            EventList.Add(eventScript);
            KnownCount++;
        }


        // Update is called once per frame
        void Update()
        {
            this.CurrentTimestamp = this.Manager.GameTimestamp;
        }
        private void OnDestroy()
        {
            running = false;
        }
    }
}