using System.Collections.Generic;
using System.IO;
using UnityEngine;
using Vuforia;

namespace RothenburgAR.Exhibition
{
    public class ExhibitionFactory
    {
        public static ExhibitionBehaviour BuildExhibition(PreloadedExhibition exhibitionData)
        {
            GameObject newExhibitionGo = new GameObject("Exhibition:" + exhibitionData.ID, typeof(ExhibitionBehaviour));
            ExhibitionBehaviour newExhibition = newExhibitionGo.GetComponent<ExhibitionBehaviour>();

            newExhibition.ID = exhibitionData.ID;
            newExhibition.DatasetPath = exhibitionData.DatasetPath;

            Debug.Log(newExhibition.ID + ": Load tracker database");
            // Create the trackers
            TrackerDatabase trackerDbGo =
                VuforiaTrackerLoader.LoadDatabase(Path.Combine(newExhibition.DatasetPath, "tracker.xml"));


            Debug.Log(newExhibition.ID + ": Rename TrackableBehaviours ");
            newExhibition.TrackerDatabase = trackerDbGo;
            var tmpList = InitializeTrackableBehaviours(trackerDbGo, newExhibition);

            Debug.Log(newExhibition.ID + ": Build Exhibits");
            foreach (var preloadedExhibit in exhibitionData.ContainedExhibits)
            {
                if (!tmpList.ContainsKey(preloadedExhibit.ID))
                {
                    Debug.LogWarning("Skipping Exhibit '" + preloadedExhibit.ID +
                                     "': No TrackableBehaviour found for exhibit with id !");
                    continue;
                }
                var currentTrackableBehaviour = tmpList[preloadedExhibit.ID];
                BuildExhibit(currentTrackableBehaviour, preloadedExhibit, newExhibition);
            }

            Debug.Log(newExhibition.ID + ": Activate Dataset");
            // Todo: Reload Tracker DB
            if (!VuforiaTrackerLoader.ActivateDataset(trackerDbGo.DataSet))
            {
                Debug.LogWarning("Could not activate the dataset of exhibition " + exhibitionData.ID);
            }

            return newExhibition;
        }

        private static Dictionary<string, TrackableBehaviour> InitializeTrackableBehaviours(
            TrackerDatabase trackerDbGo,
            ExhibitionBehaviour newExhibition)
        {
            var tmpList = new Dictionary<string, TrackableBehaviour>();
            foreach (var trackableBehaviour in trackerDbGo.TrackableBehaviours)
            {
                trackableBehaviour.name = "Tracker:" + trackableBehaviour.TrackableName;
                trackableBehaviour.transform.SetParent(newExhibition.transform);
                trackableBehaviour.gameObject.SetActive(false);
                trackableBehaviour.gameObject.AddComponent<DefaultTrackableEventHandler>();

                tmpList.Add(trackableBehaviour.TrackableName, trackableBehaviour);
            }
            return tmpList;
        }

        private static void BuildExhibit(TrackableBehaviour currentTrackableBehaviour,
            PreloadedExhibit preloadedExhibit,
            ExhibitionBehaviour newExhibition)
        {
            ExhibitBehaviour newExhibit;
            GameObject newExhibitGo;
            var newExhibitName = "Exhibit:" + preloadedExhibit.ID;
            if (currentTrackableBehaviour is ImageTargetBehaviour)
            {
                newExhibitGo = new GameObject(newExhibitName, typeof(ImageExhibitBehaviour));
                newExhibit = newExhibitGo.GetComponent<ImageExhibitBehaviour>();
            }
            else
            {
                newExhibitGo = new GameObject(newExhibitName, typeof(ExhibitBehaviour));
                newExhibit = newExhibitGo.GetComponent<ExhibitBehaviour>();
            }

            newExhibit.Exhibition = newExhibition;
            newExhibit.ID = preloadedExhibit.ID;
            newExhibit.transform.SetParent(newExhibition.transform);
            newExhibit.Tracker = currentTrackableBehaviour;

            currentTrackableBehaviour.transform.SetParent(newExhibit.transform);
            currentTrackableBehaviour.gameObject.SetActive(true);

            //  Create Title, if exists
            if (preloadedExhibit.Title.HasValue)
                newExhibit.SetTitle(preloadedExhibit.Title.Value);

            if (preloadedExhibit.Description != null)
                newExhibit.SetDescription(preloadedExhibit.Description);

            foreach (var referencedPoi in preloadedExhibit.ReferencedPoiEntries)
                newExhibit.AddPoiReference(referencedPoi);
        }
    }
}