using System;
using System.Collections.Generic;
using System.IO;
using RothenburgAR.Common;
using UnityEngine;

namespace RothenburgAR.PointOfInterest
{
    public class PoiDataManager : Singleton<PoiDataManager>
    {
        private List<string> DataSourcePathList { get; set; }
        private List<IPoiPreloader> PoiPreloaderList { get; set; }
        private Dictionary<string, PoiData> PoiDataList { get; set; }

        public PoiDataManager()
        {
            DataSourcePathList = new List<string>();
            PoiPreloaderList = new List<IPoiPreloader>();
            PoiDataList = new Dictionary<string, PoiData>();
        }

        public void AddPoiPreloader(IPoiPreloader preloader)
        {
            PoiPreloaderList.Add(preloader);
        }

        public void AddPoiDataSourcePath(string path)
        {
            // Todo: Throw Exception
            if (Directory.Exists(path))
            {
                DataSourcePathList.Add(path);
                Debug.Log("AddPoiDataSourcePath: Added source path '" + path + "'");
            }
            else
            {
                Debug.Log("AddPoiDataSourcePath: Path '" + path + "'; does not exist - ignoring");
            }
        }

        public void LoadEverySourcePath()
        {
            Debug.Log("Loading every path");
            DataSourcePathList.ForEach(LoadSourcePath);
        }

        public void LoadSourcePath(string path)
        {
            if (!Directory.Exists(path))
            {
                Debug.Log("LoadSourcePath: Path '" + path + "'; does not exist - aborting");
                return;
            }

            foreach (var directory in Directory.GetDirectories(path))
            {
                LoadPoiFromDirectPath(directory);
            }
        }


        private void LoadPoiFromDirectPath(string path)
        {
            if (!Directory.Exists(path))
            {
                Debug.Log("LoadPoiFromDirectPath: Path '" + path + "'; does not exist - aborting");
                return;
            }
            IPoiPreloader preloader = SelectPoiPreloader(path);
            if (preloader == null)
            {
                Debug.LogWarning("Could not find a valid preloader for path '" + path + "'; Ignoring");
                return;
            }
            try
            {
                var newPois = preloader.PreloadPoi(path);
                foreach (var newPoi in newPois)
                {
                    AddPoiData(newPoi);
                }
            }
            catch (Exception e)
            {
                Debug.LogError("Could not load path '" + path + "'; Ignoring; Error: " + e.Message);
            }
        }

        public void AddPoiData(PoiData newPoi)
        {
            if (PoiDataList.ContainsKey(newPoi.ID))
            {
                Debug.LogWarning("Poi with ID '" + newPoi.ID + "' already exists! Ignoring.");
                return;
            }
            PoiDataList.Add(newPoi.ID, newPoi);
            Debug.Log("Added new poi with ID '" + newPoi.ID + "'.");
        }

        private IPoiPreloader SelectPoiPreloader(string path)
        {
            IPoiPreloader selectedPreloader = null;
            // Find a valid preloader
            foreach (var preloader in PoiPreloaderList)
            {
                if (preloader.CanLoadPoiDirectory(path))
                {
                    selectedPreloader = preloader;
                    break;
                }
            }
            return selectedPreloader;
        }


        public bool HasPoiData(string id)
        {
            return PoiDataList.ContainsKey(id);
        }

        public PoiData GetPoiData(string id)
        {
            return PoiDataList[id];
        }

        public void ClearPoiDataList()
        {
            PoiDataList.Clear();
        }

        public void ClearSourcePathList()
        {
            DataSourcePathList.Clear();
        }
        public void ClearPoiPreloaderList()
        {
            PoiPreloaderList.Clear();
        }

        public void ClearAll()
        {
            ClearPoiDataList();
            ClearPoiPreloaderList();
            ClearSourcePathList();
        }
    }
}