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

/// <summary>
/// Test the User class
/// </summary>
public class TestUser : MonoBehaviour
{
    /// <summary>
    /// Start is called before the first frame update
    /// </summary>
    void Start()
    {
        TestNewUser();
        TestUserAddCourse();
        TestUserAddMinigame();
        TestGetRecentCoursesEmpty();
        TestGetRecentCoursesAll();
        TestGetRecommendedCoursesEmpty();
        TestGetRecommendedCoursesAll();
        TestGetCourseProgressNull();
        TestGetCourseProgressValid();
        TestGetMinigameProgressNull();
        TestGetMinigameProgressValid();
    }

    /// <summary>
    /// Test for the creation of a new user
    /// </summary>
    public void TestNewUser()
    {
        User user = new User();
        Debug.Assert(user != null);
        Debug.Assert(user.courses.Count == 0);
        Debug.Assert(user.minigames.Count == 0);
    }

    /// <summary>
    /// Test whether progress on a new course can be added
    /// </summary>
    public void TestUserAddCourse()
    {
        User user = new User();
        Progress p = new Progress();
        user.courses.Add(p);
        Debug.Assert(user.courses.Count == 1);
        Debug.Assert(user.minigames.Count == 0);
    }

    /// <summary>
    /// Test whether progress on a new minigame can be added
    /// </summary>
    public void TestUserAddMinigame()
    {
        User user = new User();
        Progress p = new Progress();
        user.minigames.Add(p);
        Debug.Assert(user.courses.Count == 0);
        Debug.Assert(user.minigames.Count == 1);
    }

    /// <summary>
    /// Test GetRecentCourses will return empty when no progress is stored
    /// </summary>
    public void TestGetRecentCoursesEmpty()
    {
        User user = new User();
        Debug.Assert(user.GetRecentCourses().Count == 0);
    }

    /// <summary>
    /// Temporary test for GetRecentCourses will return all progress that is stored
    /// </summary>
    public void TestGetRecentCoursesAll()
    {
        User user = new User();
        Progress p = new Progress();
        p.AddOrUpdate<CourseIndex>("courseIndex", CourseIndex.FINGERSPELLING);
        p.AddOrUpdate<float>("courseProgress", 0.5f);
        user.courses.Add(p);
        List<Tuple<CourseIndex, float>> list = user.GetRecentCourses();
        Debug.Assert(list.Count == 1);
        Debug.Assert(list[0].Item1 == CourseIndex.FINGERSPELLING);
        Debug.Assert(list[0].Item2 == 0.5f);
    }

    /// <summary>
    /// Test GetRecommendedCourses will return <c>Tuple<CourseIndex.FINGERSPELLING, 0.0></c> when no progress is stored
    /// </summary>
    public void TestGetRecommendedCoursesEmpty()
    {
        User user = new User();
        List<Tuple<CourseIndex, float>> list = user.GetRecommendedCourses();
        Debug.Assert(list.Count == 1);
        Debug.Assert(list[0].Item1 == CourseIndex.FINGERSPELLING);
        Debug.Assert(list[0].Item2 == 0.0f);
    }

    /// <summary>
    /// Temporary test for GetRecommenedCourses will return all progress that is stored
    /// </summary>
    public void TestGetRecommendedCoursesAll()
    {
        User user = new User();
        Progress p = new Progress();
        p.AddOrUpdate<CourseIndex>("courseIndex", CourseIndex.FINGERSPELLING);
        p.AddOrUpdate<float>("courseProgress", 0.5f);
        user.courses.Add(p);
        List<Tuple<CourseIndex, float>> list = user.GetRecommendedCourses();
        Debug.Assert(list.Count == 1);
        Debug.Assert(list[0].Item1 == CourseIndex.FINGERSPELLING);
        Debug.Assert(list[0].Item2 == 0.5f);
    }

    /// <summary>
    /// Test GetCourseProgress returns null when course cannot be found
    /// </summary>
    public void TestGetCourseProgressNull()
    {
        User user = new User();
        Debug.Assert(user.GetCourseProgress(CourseIndex.FINGERSPELLING) == null);
        Debug.Assert(user.GetCourseProgress((CourseIndex)100) == null);
    }

    /// <summary>
    /// Test GetCourseProgress returns correct progress object
    /// </summary>
    public void TestGetCourseProgressValid()
    {
        User user = new User();
        Progress p = new Progress();
        p.AddOrUpdate<CourseIndex>("courseIndex", CourseIndex.FINGERSPELLING);
        p.AddOrUpdate<float>("courseProgress", 3.14159265f);
        user.courses.Add(p);
        Progress q = user.GetCourseProgress(CourseIndex.FINGERSPELLING);
        Debug.Assert(q.Get<CourseIndex>("courseIndex") == CourseIndex.FINGERSPELLING);
        Debug.Assert(q.Get<float>("courseProgress") == 3.14159265f);
    }

    /// <summary>
    /// Test GetMinigameProgress returns null when minigame cannot be found
    /// </summary>
    public void TestGetMinigameProgressNull()
    {
        User user = new User();
        Debug.Assert(user.GetMinigameProgress(MinigameIndex.SPELLING_BEE) == null);
        Debug.Assert(user.GetMinigameProgress((MinigameIndex)100) == null);

        Progress p = new Progress();
        p.AddOrUpdate<MinigameIndex>("minigameIndex", MinigameIndex.SPELLING_BEE);
        user.minigames.Add(p);
        Debug.Assert(user.GetMinigameProgress(MinigameIndex.HANGMAN) == null);
    }

    /// <summary>
    /// Test GetMinigameProgress returns correct progress object
    /// </summary>
    public void TestGetMinigameProgressValid()
    {
        User user = new User();
        Progress p = new Progress();
        p.AddOrUpdate<MinigameIndex>("minigameIndex", MinigameIndex.SPELLING_BEE);
        user.minigames.Add(p);
        Progress q = user.GetMinigameProgress(MinigameIndex.SPELLING_BEE);
        Debug.Assert(q.Get<CourseIndex>("minigameIndex") == CourseIndex.FINGERSPELLING);
    }
}
