﻿using System.Collections;
using System.Collections.Generic;
using System;
using System.IO;
using System.Text;
using UnityEngine;
using UnityEditor;

[CustomEditor(typeof(T1ModelMono))]
public class T1ModelEditor : Editor
{
    public T1Model sModel;
    private string modelLoadPath;
    public string ModelLoadPath
    {
        get { return modelLoadPath; }
        set
        {
            if (modelLoadPath != value)
            {
                modelLoadPath = value;
                EditorPrefs.SetString("T1.modelLoadPath", modelLoadPath);
            }
        }
    }
    private string modelSavePath;
    public string ModelSavePath
    {
        get { return modelSavePath; }
        set
        {
            if (modelSavePath != value)
            {
                modelSavePath = value;
                EditorPrefs.SetString("T1.modelSavePath", modelSavePath);
            }
        }
    }
    private string matSavePath;
    public string MatSavePath
    {
        get { return matSavePath; }
        set
        {
            if (matSavePath != value)
            {
                matSavePath = value;
                EditorPrefs.SetString("T1.matSavePath", matSavePath);
            }
        }
    }
    private string matTexPath;
    public string MatTexPath
    {
        get { return matTexPath; }
        set
        {
            if (matTexPath != value)
            {
                matTexPath = value;
                EditorPrefs.SetString("T1.matTexPath", matTexPath);
            }
        }
    }
    private string modelName;
    public string ModelName {
        get { return modelName; }
        set {
            if (modelName != value) {
                modelName = value;
                EditorPrefs.SetString("T1.modelName", modelName);
            }
        }
    }
    private float modelScale;
    public float ModelScale
    {
        get { return modelScale; }
        set
        {
            if (modelScale != value)
            {
                modelScale = value;
                EditorPrefs.SetFloat("T1.modelScale", modelScale);
            }
        }
    }
    private bool modelIsActor;
    public bool ModelIsActor
    {
        get { return modelIsActor; }
        set
        {
            if (modelIsActor != value)
            {
                modelIsActor = value;
                EditorPrefs.SetBool("T1.modelIsActor", modelIsActor);
            }
        }
    }
    private SerializedProperty modelProp;
    private SerializedProperty modelGOProp;

    void OnEnable()
    {
        modelProp = serializedObject.FindProperty("sModel");
        modelGOProp = serializedObject.FindProperty("modelGO");
        ModelLoadPath = EditorPrefs.GetString("T1.modelLoadPath");
        ModelSavePath = EditorPrefs.GetString("T1.modelSavePath");
        MatSavePath = EditorPrefs.GetString("T1.matSavePath");
        MatTexPath = EditorPrefs.GetString("T1.matTexPath", "textures/");
        ModelName = EditorPrefs.GetString("T1.modelName");
        ModelScale = EditorPrefs.GetFloat("T1.modelScale", 256.0f);
        ModelIsActor = EditorPrefs.GetBool("T1.modelIsActor", false);
    }

    //Rotates the vertices of the mesh
    public void RotateMesh(Mesh mesh, float x, float y, float z)
    {
        Vector3[] vertices = mesh.vertices;

        Vector3 center = new Vector3(0.0f, 0.0f, 0.0f);
        Quaternion rotation = new Quaternion();
        rotation.eulerAngles = new Vector3(x, y, z);

        //mesh.Clear();
        for (int i = 0; i < vertices.Length; i++)
        {
            vertices[i] = rotation * (vertices[i] - center) + center;
        }

        mesh.vertices = vertices;
    }

    public void TryRotateModelGO(GameObject go, float x, float y, float z)
    {
        if (go != null)
        {
            if (EditorUtility.DisplayDialog("Warning", "This action will permanently rotate all the meshes in the GameObject " + go.name + " and it's children. This can not be undone. Proceed?", "Yes", "No"))
            {
                MeshFilter[] meshFilters = go.GetComponentsInChildren<MeshFilter>();
                foreach (MeshFilter mf in meshFilters)
                {
                    RotateMesh(mf.sharedMesh, x, y, z);
                }
            }
        }
    }

    public void SetModelBounds(T1Model model)
    {
        if (ModelIsActor)
        {
            model.CalculateBounds();
        }
        else
        {
            model.ClearBounds();
        }
    }

    public override void OnInspectorGUI()
    {
        T1ModelMono mb = target as T1ModelMono;
        sModel = mb.sModel;

        serializedObject.Update();

        EditorGUILayout.Space();
        GUILayout.BeginHorizontal();
        if (GUILayout.Button("Load File"))
        {
            string path = EditorUtility.OpenFilePanel("Open T1 Model file", ModelLoadPath, "bin");
            if (!string.IsNullOrEmpty(path))
            {
                ModelLoadPath = Path.GetDirectoryName(path);
                ModelName = Path.GetFileNameWithoutExtension(path);
                sModel.LoadModel(path);
            }
        }

        if (GUILayout.Button("Save File"))
        {
            string path = EditorUtility.SaveFilePanel("Save T1 Model file", ModelSavePath, ModelName, "bin");
            if (!string.IsNullOrEmpty(path))
            {
                ModelSavePath = Path.GetDirectoryName(path);
                ModelName = Path.GetFileNameWithoutExtension(path);
                sModel.SaveModel(path);
            }
        }
        GUILayout.EndHorizontal();

        ModelName = EditorGUILayout.TextField("Filename", ModelName);
        MatTexPath = EditorGUILayout.TextField("kMat Texture Path", MatTexPath);

        GUILayout.BeginHorizontal();
        bool isActor = EditorGUILayout.Toggle("Is an Actor?", ModelIsActor);
        if (isActor != ModelIsActor)
        {
            ModelIsActor = isActor;
            SetModelBounds(sModel);
        }
        GUILayout.FlexibleSpace();
        GUILayout.EndHorizontal();

        GUILayout.BeginHorizontal();
        EditorGUILayout.PropertyField(modelGOProp, new GUIContent(""), true);
        //mb.modelGO = (GameObject)EditorGUILayout.ObjectField(mb.modelGO, typeof(GameObject), true);
        if (GUILayout.Button("Create Model"))
        {
            GameObject go = mb.modelGO;
            mb.sModel = new T1Model();
            sModel = mb.sModel;

            sModel.ProcessTransformNode(ModelName, go.transform);
            sModel.FlipVertsX();
            sModel.FlipWindingOrder();
            sModel.Rotate(90.0f, 0.0f, 0.0f);
            sModel.Scale(256.0f);
            SetModelBounds(sModel);
        }

        if (GUILayout.Button("Create kMat"))
        {
            string path = EditorUtility.SaveFilePanel("Save KMat file", MatSavePath, modelName, "kmat");
            if (!string.IsNullOrEmpty(path))
            {
                MatSavePath = Path.GetDirectoryName(path);

                //Get all Materials used
                MeshRenderer[] renderers = mb.modelGO.GetComponentsInChildren<MeshRenderer>();
                List<Material> mats = new List<Material>();
                foreach (MeshRenderer mr in renderers)
                    mats.AddRange(mr.sharedMaterials);

                sModel.SaveKMat(ModelName, path, MatTexPath, mats.ToArray());
            }
        }
        GUILayout.EndHorizontal();

        EditorGUILayout.Space();

        GUILayout.BeginHorizontal();
        GUILayout.FlexibleSpace();
        if (GUILayout.Button("Validate and Fix Errors"))
        {
            sModel.Validate();
        }
        GUILayout.FlexibleSpace();
        GUILayout.EndHorizontal();

        EditorGUILayout.LabelField("", GUI.skin.horizontalSlider);

        //GUILayout.BeginHorizontal();
        //ModelScale = EditorGUILayout.FloatField(ModelScale);
        //if (GUILayout.Button("Scale Model"))
        //{
        //    sModel.Scale(ModelScale);
        //}
        //GUILayout.EndHorizontal();

        //GUILayout.BeginHorizontal();
        //float lastLabelWidth = EditorGUIUtility.labelWidth;
        //EditorGUIUtility.labelWidth = 50.0f;
        //EditorGUILayout.LabelField("Rotate Mesh", GUILayout.ExpandWidth(false));
        //EditorGUIUtility.labelWidth = lastLabelWidth;

        //GUILayout.BeginVertical();
        //if (GUILayout.Button("X -90")) TryRotateModelGO(mb.modelGO, -90.0f, 0.0f, 0.0f);
        //Color lastColor = GUI.color;
        //GUI.color = new Color(0.88f, 1.0f, 0.88f);
        //if (GUILayout.Button("X +90")) TryRotateModelGO(mb.modelGO, 90.0f, 0.0f, 0.0f);
        //GUI.color = lastColor;
        //GUILayout.EndVertical();

        //GUILayout.BeginVertical();
        //if (GUILayout.Button("Y -90")) TryRotateModelGO(mb.modelGO, 0.0f, -90.0f, 0.0f);
        //if (GUILayout.Button("Y +90")) TryRotateModelGO(mb.modelGO, 0.0f, 90.0f, 0.0f);
        //GUILayout.EndVertical();

        //GUILayout.BeginVertical();
        //if (GUILayout.Button("Z -90")) TryRotateModelGO(mb.modelGO, 0.0f, 0.0f, -90.0f);
        //if (GUILayout.Button("Z +90")) TryRotateModelGO(mb.modelGO, 0.0f, 0.0f, 90.0f);
        //GUILayout.EndVertical();

        //GUILayout.EndHorizontal();

        //EditorGUILayout.LabelField("", GUI.skin.horizontalSlider);

        //base.OnInspectorGUI();
        EditorUtility.SetDirty(target);
        EditorGUILayout.PropertyField(modelProp, new GUIContent("Model"), true);
        
        serializedObject.ApplyModifiedProperties();
    }
}
