using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using UnityEngine.SceneManagement;


public class ExperimentManager9_2afc : MonoBehaviour
{
    [SerializeField] private GameObject target1;
    [SerializeField] private GameObject target2;
    [SerializeField] private TMP_Text message;
    [SerializeField] private Button left_button;
    [SerializeField] private Button right_button;
    [SerializeField] private GameObject canvas;
    [SerializeField] private Button exit_button;

    TwoBlockTrial[] trials;
    private int[] responses;
    private int trial = 0;

    private Dictionary<string,AudioClip> clips;
    private Dictionary<string,Material> materials;

    private float show_time = float.MaxValue;

    private Vector3 reset_position_1;
    private Quaternion reset_rotation_1;
    private Vector3 reset_scale_1;

    private Vector3 reset_position_2;
    private Quaternion reset_rotation_2;
    private Vector3 reset_scale_2;

    // Start is called before the first frame update
    void Start()
    {
        // allocate arrays to match fields
        trials = Configurator.config.GetTwoBlockExperiment();
        responses = new int[trials.Length];

        // locate audio clips and materials, if using
        List<string> soundNames = Configurator.config.AvailableSounds();
        clips = new Dictionary<string, AudioClip>();

        for ( int ii = 0; ii < soundNames.Count; ++ii )
        {
            if ( clips[soundNames[ii]] = Resources.Load<AudioClip>(soundNames[ii]))
            {
            }
            else
            {
                Debug.Log($"Unable to load clip {soundNames[ii]}");
            }
        }

        materials = new Dictionary<string, Material>();
        for ( int ii = 0; ii < Configurator.colours.Length; ++ii )
        {
            materials[Configurator.colours[ii]] = Resources.Load<Material>(Configurator.colours[ii]);
        }

        reset_position_1 = target1.transform.position;
        reset_rotation_1 = target1.transform.rotation;
        reset_scale_1 = target1.transform.localScale;

        reset_position_2 = target2.transform.position;
        reset_rotation_2 = target2.transform.rotation;
        reset_scale_2 = target2.transform.localScale;

        // set initial values
        ConfigureTrial();

        // listen for button clicks
        left_button.onClick.AddListener(delegate {Respond(0);});
        right_button.onClick.AddListener(delegate {Respond(1);});

        canvas.SetActive(false);
        show_time = Time.time + 1.5f;
    }

    void ConfigureTrial ()
    {
        TwoBlockTrial t = trials[trial];

        target1.GetComponent<Rigidbody>().mass = t.block1.mass;
        target1.transform.localScale = new Vector3(t.block1.size * reset_scale_1.x,
                                                   t.block1.size * reset_scale_1.y,
                                                   t.block1.size * reset_scale_1.z);
        if ( t.block1.sound != "" )
        {
            target1.GetComponent<AudioSource>().clip = clips[t.block1.sound];
        }

        if ( t.block1.material != "" )
        {
            target1.GetComponent<MeshRenderer>().material = materials[t.block1.material];
        }

        target2.GetComponent<Rigidbody>().mass = t.block2.mass;
        target2.transform.localScale = new Vector3(t.block2.size * reset_scale_2.x,
                                                   t.block2.size * reset_scale_2.y,
                                                   t.block2.size * reset_scale_2.z);
        if ( t.block2.sound != "" )
        {
            target2.GetComponent<AudioSource>().clip = clips[t.block2.sound];
        }

        if ( t.block2.material != "" )
        {
            target2.GetComponent<MeshRenderer>().material = materials[t.block2.material];
        }

        message.text = $"[{Configurator.config.experiment}: {trial + 1}/{trials.Length}] Which block feels heavier?";
    }

    // log an experiment response
    void Respond ( int response )
    {
        responses[trial] = response;

        Debug.Log($"response received: {response}");

        trial += 1;
        if ( trial >= trials.Length )
        {
            message.text = $"Experiment complete. Saved to '{Configurator.config.experiment}.csv'.";
            left_button.gameObject.SetActive(false);
            right_button.gameObject.SetActive(false);
            exit_button.gameObject.SetActive(true);
            SaveResults();
        }
        else
        {
            ConfigureTrial();
        }

        canvas.SetActive(false);
        show_time = Time.time + 1.5f;
    }

    void Update()
    {
        if ( Time.time >= show_time )
        {
            show_time = float.MaxValue;
            canvas.SetActive(true);
        }
    }

    void SaveResults()
    {
        string outfile = Path.Combine(Application.persistentDataPath, $"{Configurator.config.experiment}.csv");
        Debug.Log(outfile);

        using StreamWriter writer = new StreamWriter(outfile);
        writer.WriteLine($"Trial,{TwoBlockTrial.Header()},Response");
        for (int ii = 0; ii < trials.Length; ++ii)
        {
            writer.WriteLine($"{ii + 1},{trials[ii].Values()},{responses[ii]}");
        }
    }

    public void Exit ()
    {
        SceneManager.LoadScene("SettingsScreen");
    }
}
