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

namespace RothenburgAR.Common
{
    public class TextElement
    {
        private Dictionary<string, TextEntryLanguageEntry> TextEntries { get; set; }

        public int EntryAmount
        {
            get { return TextEntries.Count; }
        }

        public TextElement()
        {
            TextEntries = new Dictionary<string, TextEntryLanguageEntry>();
        }

        public void AddTextElement(string languageKey, TextEntryType type, string value)
        {
            if (type == TextEntryType.Invalid)
                return;

            if (TextEntries.ContainsKey(languageKey))
                throw new Exception("Already defined: " + languageKey);

            TextEntries.Add(languageKey, new TextEntryLanguageEntry(type, value));
        }

        public string GetTextByLanguage(string langKey)
        {
            TextEntryLanguageEntry te;
            if (TextEntries.TryGetValue(langKey, out te)) return te.Text;

            if (LanguageManager.Instance.DefaultLanguageKey != langKey)
                return GetTextByLanguage(LanguageManager.Instance.DefaultLanguageKey);
            else
                return LanguageManager.ERR_NO_TEXT_FOR_LANG;
        }

        public static TextEntryType GetTextEntryTypeFromString(string text)
        {
            switch (text.ToLower())
            {
                case "inline":
                    return TextEntryType.Inline;
                case "file":
                    return TextEntryType.File;
                default:
                    return TextEntryType.Invalid;
            }
        }

        public static TextElement BuildFromXmlNode(string basePath, XmlNodeList xmlNodeList)
        {
            TextElement textElement = new TextElement();
            foreach (XmlNode xmlNode in xmlNodeList)
            {
                if (xmlNode == null || xmlNode.Attributes == null)
                    throw new ArgumentNullException();
                if (xmlNode.Attributes["lang"] == null)
                    throw new Exception("Attribute lang is not defined.");
                if (xmlNode.Attributes["value"] == null)
                    throw new Exception("Attribute value is not defined.");
                if (xmlNode.Attributes["type"] == null)
                    throw new Exception("Attribute type is not defined.");


                var langCode = xmlNode.Attributes["lang"].Value;
                var typeStr = xmlNode.Attributes["type"].Value;


                TextEntryType type = TextElement.GetTextEntryTypeFromString(typeStr);
                var valueStr = xmlNode.Attributes["value"].Value;
                if (type == TextEntryType.File)
                {
                    var file = Resources.Load<TextAsset>(valueStr);
                    if (file != null)
                    {
                        valueStr = file.text;
                        type = TextEntryType.Inline;
                    }
                    else
                    {
                        valueStr = Path.Combine(basePath, valueStr);
                    }
                }
                textElement.AddTextElement(langCode, type, valueStr);
            }
            return textElement;
        }
    }

    public enum TextEntryType
    {
        Invalid = 0,
        Inline = 1,
        File = 2
    }

    public class TextEntryLanguageEntry
    {
        private string Value { get; set; }
        private TextEntryType Type { get; set; }

        public string Text
        {
            get
            {
                // If it is an Inline-Text, just return it
                if (Type == TextEntryType.Inline)
                    return Value;

                // If it is no inline text, we need to have a file path as "value".
                if (!File.Exists(Value))
                    throw new FileNotFoundException();

                // Attention: 
                // if there should be performance issues, here could be a nice place to add caching
                return File.ReadAllText(Value, System.Text.Encoding.UTF8);
            }
        }

        public TextEntryLanguageEntry(TextEntryType type, string value)
        {
            Value = value;
            Type = type;
        }
    }
}