/*
Author:		Jan Lygnos
Date:		12.8.2019
Last Edit:  13.8.2019
*/

using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(AudioDatabaseAsset))]
public class AudioDatabaseAssetEditor : Editor {

    private AudioDatabaseAsset audioDatabase;
    private SerializedObject audioDatabaseSerialized;
    private SerializedProperty registeredAudio;

    private static GUIContent
        moveButtonContent = new GUIContent("\u21b4", "move down"),
        deleteButtonContent = new GUIContent("-", "delete"),
        playButtonContent = new GUIContent("\u25BA", "play");

    private void OnEnable() {
        audioDatabase = (AudioDatabaseAsset)target;
        audioDatabaseSerialized = new SerializedObject(audioDatabase);
    }

    public override void OnInspectorGUI() {
        audioDatabaseSerialized.Update();
        registeredAudio = audioDatabaseSerialized.FindProperty("RegisteredAudio");

        DisplayElements(registeredAudio);
        EditorGUILayout.Space();

        if (GUILayout.Button("Add Audio")) {
            if (audioDatabase.RegisteredAudio == null) audioDatabase.RegisteredAudio = new List<Audio>();
            audioDatabase.RegisteredAudio.Add(new Audio());
        }

        audioDatabaseSerialized.ApplyModifiedProperties();
        serializedObject.ApplyModifiedProperties();
    }

    private void DisplayElements(SerializedProperty list) {

        if (list.arraySize > 0) {
            EditorGUILayout.PropertyField(list);
            EditorGUI.indentLevel += 1;

            if (list.isExpanded) {
                for (int i = 0; i < list.arraySize; i++) {
                    EditorGUILayout.BeginHorizontal();
                    EditorGUILayout.PropertyField(list.GetArrayElementAtIndex(i));
                    ShowButtons(list, i);
                    EditorGUILayout.EndHorizontal();

                    if (list.GetArrayElementAtIndex(i).isExpanded) {
                        EditorGUILayout.PropertyField(list.GetArrayElementAtIndex(i).FindPropertyRelative("Name"));
                        EditorGUI.BeginChangeCheck();
                        EditorGUILayout.PropertyField(list.GetArrayElementAtIndex(i).FindPropertyRelative("AudioClip"));
                        if (EditorGUI.EndChangeCheck()) {
                            if (audioDatabase.RegisteredAudio[i].AudioClip != null) {
                                audioDatabase.RegisteredAudio[i].Name = audioDatabase.RegisteredAudio[i].AudioClip.name;
                            }
                            audioDatabaseSerialized.ApplyModifiedProperties();
                            serializedObject.ApplyModifiedProperties();
                        }
                        EditorGUILayout.Slider(list.GetArrayElementAtIndex(i).FindPropertyRelative("Volume"), 0f, 1f);
                    }
                }
            }

            EditorGUI.indentLevel -= 1;
        } else {
            GUILayout.Label("No Audios registered.");
        }
    }

    private void ShowButtons(SerializedProperty list, int index) {
        if (GUILayout.Button(deleteButtonContent, EditorStyles.miniButtonRight, GUILayout.Width(20f))) {
            audioDatabase.RegisteredAudio.RemoveAt(index);
        }

        if (GUILayout.Button(moveButtonContent, EditorStyles.miniButtonLeft, GUILayout.Width(20f))) {
            if (index != audioDatabase.RegisteredAudio.Count - 1) {
                Audio first = audioDatabase.RegisteredAudio[index];
                Audio second = audioDatabase.RegisteredAudio[index + 1];
                audioDatabase.RegisteredAudio[index] = second;
                audioDatabase.RegisteredAudio[index + 1] = first;
            }
        }

        if (GUILayout.Button(playButtonContent, EditorStyles.miniButtonMid, GUILayout.Width(20f))) {
            PlayClip(audioDatabase.RegisteredAudio[index].AudioClip);
        }
    }

    private static void PlayClip(AudioClip clip, int startSample = 0, bool loop = false) {
        Assembly unityEditorAssembly = typeof(AudioImporter).Assembly;
        Type audioUtilClass = unityEditorAssembly.GetType("UnityEditor.AudioUtil");

        MethodInfo method = audioUtilClass.GetMethod("PlayClip", BindingFlags.Static | BindingFlags.Public,
            null, new System.Type[] { typeof(AudioClip), typeof(int), typeof(bool) }, null);
        method.Invoke(null, new object[] { clip, startSample, loop });
    }
}