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

public class Configurator : MonoBehaviour
{
    // shared singleton instance
    public static Configurator config;

    // configurable parameters
    public int num_trials = 40;

    public float mass_lo = 0.5f;
    public float mass_hi = 2.5f;

    public float size_lo = 0.5f;
    public float size_hi = 2.0f;


    public bool use2AFC = false;

    public bool useTones = false;
    public bool useBass = false;
    public bool useChimes = false;
    public bool usePiano = false;

    public bool useColours = false;

    public string experiment = "XXXX";


    // available resources
    private static string[] tones = {"C2_66", "C3_130", "C4_262", "C5_525", "C6_1046", "C7_2100"};
    private static string[] basses = {"bass-C1", "bass-C2", "bass-C3", "bass-C4", "bass-C5", "bass-C6"};
    private static string[] chimes = {"chime-C1", "chime-C2", "chime-C3", "chime-C4", "chime-C5", "chime-C6"};
    private static string[] pianos = {"piano-C1", "piano-C2", "piano-C3", "piano-C4", "piano-C5", "piano-C6"};
    public static string[] colours = {"red", "green", "yellow", "blue", "black", "white", "grey"};


    void Awake()
    {
        // don't overwrite the singleton
        if (config != null)
        {
            return;
        }

        // stash shared instance and immortalise object it belongs to
        config = this;
        DontDestroyOnLoad(gameObject);
    }

    public List<string> AvailableSounds()
    {
        List<string> result = new List<string>();

        if ( useTones ) { result.AddRange(tones); }
        if ( useBass ) { result.AddRange(basses); }
        if ( useChimes ) { result.AddRange(chimes); }
        if ( usePiano ) { result.AddRange(pianos); }

        if ( result.Count == 0 ) { result.Add(""); }

        return result;
    }

    public SingleBlockTrial[] GetSingleBlockExperiment()
    {
        SingleBlockTrial[] trials = new SingleBlockTrial[num_trials];
        List<string> sounds = AvailableSounds();

        for ( int ii = 0; ii < num_trials; ++ii )
        {
            float mass = Random.Range(mass_lo, mass_hi);
            float size = Random.Range(size_lo, size_hi);
            
            string sound = sounds[Random.Range(0,sounds.Count)];
            string material = useColours ? colours[Random.Range(0,colours.Length)] : "";

            trials[ii] = new SingleBlockTrial(mass, size, sound, material);
        }

        return trials;
    }

    public TwoBlockTrial[] GetTwoBlockExperiment()
    {
        TwoBlockTrial[] trials = new TwoBlockTrial[num_trials];
        List<string> sounds = AvailableSounds();

        for ( int ii = 0; ii < num_trials; ++ii )
        {
            float mass1 = Random.Range(mass_lo, mass_hi);
            float size1 = Random.Range(size_lo, size_hi);
            string sound1 = sounds[Random.Range(0,sounds.Count)];
            string material1 = useColours ? colours[Random.Range(0,colours.Length)] : "";

            float mass2 = Random.Range(mass_lo, mass_hi);
            float size2 = Random.Range(size_lo, size_hi);
            string sound2 = sounds[Random.Range(0,sounds.Count)];
            string material2 = useColours ? colours[Random.Range(0,colours.Length)] : "";

            trials[ii] = new TwoBlockTrial(mass1, size1, sound1, material1, mass2, size2, sound2, material2);
        }

        return trials;       
    }

    public static string RandomString(int length)
    {
        char[] chars = new char[length];
        for ( int ii = 0 ; ii < length; ++ii )
        {
            chars[ii] = (char) ('A' + Random.Range(0, 25));
        }

        return new string(chars);
    }

    public void NewExperimentName ( string ext = "csv" )
    {
        do
        {
            experiment = RandomString(4);
        }
        while ( File.Exists(Path.Combine(Application.persistentDataPath, $"{experiment}.{ext}")) );
    }

    public static bool IsLooped ( string clip )
    {
        return tones.Contains(clip);
    }
}
