using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class PlayerAchievement : PDictionary
{
    public enum Difficulty
    {
        Unknown = 0,
        Easy,
        Medium,
        Hard
    }

    public PlayerAchievement()
    {
    }

    public PlayerAchievement(Dictionary<string, object> data)
    {
        foreach (var x in data.Keys)
        {
            if (x == "player")
            {
                player = new PlayerAward((Dictionary<string, object>) data["player"]);
                continue;
            }

            if (x == "friends")
            {
                var frarr = (List<object>) data[x];
                var fawards = new List<PlayerAward>();
                fawards.AddRange(from object t in frarr select new PlayerAward((Dictionary<string, object>) t));
                friends = fawards;
                continue;
            }

            this[x] = data[x];
        }
    }

    public string achievement
    {
        get { return GetString("achievement"); }
        set { SetProperty("achievement", value); }
    }

    public string description
    {
        get { return GetString("description"); }
        set { SetProperty("description", value); }
    }

    public string achievementkey
    {
        get { return GetString("achievementkey"); }
        set { SetProperty("achievementkey", value); }
    }

    public string source
    {
        get { return GetString("source"); }
        set { SetProperty("source", value); }
    }

    public string playerid
    {
        get { return GetString("playerid"); }
        set { SetProperty("playerid", value); }
    }

    public string difficulty
    {
        get { return GetString("difficulty"); }
        set { SetProperty("difficulty", value); }
    }

    public string playername
    {
        get { return GetString("playername"); }
        set { SetProperty("playername", value); }
    }

    public Dictionary<string, object> fields
    {
        get
        {
            return ContainsKey("fields") ? (Dictionary<string, object>) this["fields"] : new Dictionary<string, object>();
        }
        set { SetProperty("fields", value); }
    }

    public PlayerAward player
    {
        get { return ContainsKey("player") ? (PlayerAward) this["player"] : null; }
        private set { SetProperty("player", value); }
    }

    public List<PlayerAward> friends
    {
        get { return ContainsKey("friends") ? (List<PlayerAward>) this["friends"] : null; }
        private set { SetProperty("friends", value); }
    }

    public bool allowduplicates
    {
        get { return ContainsKey("allowduplicates") && (bool) this["allowduplicates"]; }
        set { SetProperty("allowduplicates", value); }
    }

    public bool overwrite
    {
        get { return ContainsKey("overwrite") && (bool) this["overwrite"]; }
        set { SetProperty("overwrite", value); }
    }

    public DateTime updated_at
    {
        get
        {
            if (ContainsKey("updated_at"))
            {
                var result = this["updated_at"] as string;

                if (!string.IsNullOrEmpty(result))
                    return DateTime.Parse(result);
            }

            return DateTime.UtcNow;
        }
        set { this["updated_at"] = value.ToFileTimeUtc(); }
    }

    public Texture2D IconTexture { get; set; }

    public string DateAchieved { get; private set; }

    public Difficulty DifficultyValue { get; private set; }

    /// <summary>
    ///     Has the user unlocked this achievement?
    /// </summary>
    public bool HasUserUnlocked
    {
        get { return player != null; }
    }

    /// <summary>
    ///     Downloads and caches <see cref="DateAchieved" /> and <see cref="IconTexture" />.
    /// </summary>
    public void AsyncCache(MonoBehaviour host)
    {
        DateAchieved = updated_at.ToLongDateString();

        DifficultyValue = ParseDifficulty(difficulty);

        if (IconTexture == null)
        {
            var iconCache = GetString("icon");

            if (!string.IsNullOrEmpty(iconCache))
            {
                host.StartCoroutine(CR_LoadIconAsync(iconCache));
            }
            else
            {
                Debug.LogError("Achievement " + achievement + " had no icon!");
            }
        }
    }

    private static Difficulty ParseDifficulty(string value)
    {
        switch (value)
        {
            case "easy":
                return Difficulty.Easy;
            case "medium":
                return Difficulty.Medium;
            case "hard":
                return Difficulty.Hard;
            default:
                return Difficulty.Unknown;
        }
    }

    private IEnumerator CR_LoadIconAsync(string iconFilename)
    {
        WWW www;
#if !UNITY_EDITOR
		if (!string.IsNullOrEmpty(Idnet.I.RefererDomain))
		{
			// Get substring. (like media2.y8.com and not the full url)
			var RefererDomain = Idnet.I.RefererDomain.Replace("http://", "").Replace("https://", "").Replace("file://", "");
			var achievementsUrl = RefererDomain.Substring(0, RefererDomain.IndexOf("/", StringComparison.Ordinal));

			www = new WWW("https://cdn.y8.com/achievements/" + Idnet.AppId + '/' + iconFilename+"?host="+achievementsUrl);
		}
		else
		{
			www = new WWW("https://cdn.y8.com/achievements/" + Idnet.AppId + '/' + iconFilename+"?client_id="+Idnet.AppId);
		}
		#else
        www =
            new WWW("https://cdn.y8.com/achievements/" + Idnet.AppId + '/' + iconFilename + "?client_id=" + Idnet.AppId);
#endif

        yield return www;

        if (!string.IsNullOrEmpty(www.error) || www.texture == null)
        {
            Debug.LogError("Image failed to load for achievement " + achievement);
        }

        IconTexture = www.texture;
    }
}