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

public class LevelCreator : EditorWindow
{
    private static string m_DirPath = Application.dataPath + "/LevelModels/";
    private static string m_FileName = "";
    private static string m_Extension = ".txt";
    private List<string> m_Lines;

    [MenuItem("Tools/Level Creator")]
    public static void ShowWindow()
    {
        // Show existing window instance. If one doesn't exist, make one.
        EditorWindow.GetWindow(typeof(LevelCreator));
    }

    void OnGUI()
    {
        GUILayout.BeginHorizontal();
        {
            GUILayout.Label("File name : ", GUILayout.Width(100));
            m_FileName = GUILayout.TextField(m_FileName);
        }
        GUILayout.EndHorizontal();

        GUILayout.BeginHorizontal();
        if(GUILayout.Button("Create LVL !", GUILayout.Width(100)))
        {
            // Open the file
            m_Lines = new List<string>();
            StreamReader file = new StreamReader(m_DirPath + m_FileName + m_Extension);
            // Read it
            string content = "";
            while ((content = file.ReadLine()) != null)
            {
                m_Lines.Add(content);
            }
            // Close the file
            file.Close();
            // Create the level
            // -> Create the parent node
            GameObject parentNode = Instantiate(Resources.Load("Prefabs/GameObject"), Vector3.zero, Quaternion.identity) as GameObject;
            parentNode.name = "Level creator";
            // Brick script pattern
            Brick brickPattern = (Instantiate(Resources.Load("ScriptPatterns/Brick")) as GameObject).GetComponent<Brick>();
            // Additional cubes
            Dictionary<Transform, Dictionary<Vector3, int>> addCubes = new Dictionary<Transform, Dictionary<Vector3, int>>();
            // -> Create the cubes
            for(int y=0; y<m_Lines.Count; ++y)
            {
                GameObject lineNode = Instantiate(Resources.Load("Prefabs/GameObject")) as GameObject;
                lineNode.name = "Line " + (m_Lines.Count - y);
                lineNode.transform.parent = parentNode.transform;
                lineNode.transform.localPosition = Vector3.zero;
                lineNode.transform.localRotation = Quaternion.identity;
                addCubes.Add(lineNode.transform, new Dictionary<Vector3, int>());
                for (int x = 0; x < m_Lines[y].Length; ++x)
                {
                    int z = int.Parse(m_Lines[y][x].ToString());
                    int type = 1;
                    // Top test
                    // -> There is nothing on top
                    if ((y - 1) < 0)
                    {
                        //type += 2;
                    }
                    // -> There is a cube, but its z in superior (behind)
                    else if(int.Parse(m_Lines[y - 1][x].ToString()) > z)
                    {
                        type += 2;

                        // Test if we must add cube between the current cube and the top one
                        int dif = int.Parse(m_Lines[y - 1][x].ToString()) - z;
                        dif -= 1;
                        while (dif > 0)
                        {
                            // Add cube(s) between them
                            if (addCubes[lineNode.transform].ContainsKey(new Vector3(x, m_Lines.Count - (y + 1), z + dif)))
                            {
                                addCubes[lineNode.transform][new Vector3(x, m_Lines.Count - (y + 1), z + dif)] += 2;
                            }
                            else
                            {
                                addCubes[lineNode.transform].Add(new Vector3(x, m_Lines.Count - (y + 1), z + dif), 2);
                            }
                            dif -= 1;
                        }
                    }
                    // Bot test
                    if ((y + 1) >= m_Lines.Count)
                    {
                        //type += 4;
                    }
                    else if (int.Parse(m_Lines[y + 1][x].ToString()) > z)
                    {
                        type += 4;

                        // Test if we must add cube between the current cube and the top one
                        int dif = int.Parse(m_Lines[y + 1][x].ToString()) - z;
                        dif -= 1;
                        while (dif > 0)
                        {
                            // Add cube(s) between them
                            if (addCubes[lineNode.transform].ContainsKey(new Vector3(x, m_Lines.Count - (y + 1), z + dif)))
                            {
                                addCubes[lineNode.transform][new Vector3(x, m_Lines.Count - (y + 1), z + dif)] += 4;
                            }
                            else
                            {
                                addCubes[lineNode.transform].Add(new Vector3(x, m_Lines.Count - (y + 1), z + dif), 4);
                            }
                            dif -= 1;
                        }
                    }
                    // Left test
                    if ((x - 1) < 0)
                    {
                        //type += 8;
                    }
                    else if (int.Parse(m_Lines[y][x - 1].ToString()) > z)
                    {
                        type += 8;

                        // Test if we must add cube between the current cube and the top one
                        int dif = int.Parse(m_Lines[y][x - 1].ToString()) - z;
                        dif -= 1;
                        while (dif > 0)
                        {
                            // Add cube(s) between them
                            if (addCubes[lineNode.transform].ContainsKey(new Vector3(x, m_Lines.Count - (y + 1), z + dif)))
                            {
                                addCubes[lineNode.transform][new Vector3(x, m_Lines.Count - (y + 1), z + dif)] += 8;
                            }
                            else
                            {
                                addCubes[lineNode.transform].Add(new Vector3(x, m_Lines.Count - (y + 1), z + dif), 8);
                            }
                            dif -= 1;
                        }
                    }
                    // Right test
                    if ((x + 1) >= m_Lines[y].Length)
                    {
                        //type += 16;
                    }
                    else if (int.Parse(m_Lines[y][x + 1].ToString()) > z)
                    {
                        type += 16;

                        // Test if we must add cube between the current cube and the top one
                        int dif = int.Parse(m_Lines[y][x + 1].ToString()) - z;
                        dif -= 1;
                        while (dif > 0)
                        {
                            // Add cube(s) between them
                            if (addCubes[lineNode.transform].ContainsKey(new Vector3(x, m_Lines.Count - (y + 1), z + dif)))
                            {
                                addCubes[lineNode.transform][new Vector3(x, m_Lines.Count - (y + 1), z + dif)] += 16;
                            }
                            else
                            {
                                addCubes[lineNode.transform].Add(new Vector3(x, m_Lines.Count - (y + 1), z + dif), 16);
                            }
                            dif -= 1;
                        }
                    }
                    GameObject node = Instantiate(Resources.Load("Bricks/" + type)) as GameObject;
                    node.transform.parent = lineNode.transform;
                    node.transform.localPosition = new Vector3(x, m_Lines.Count - (y + 1), z);
                    node.transform.localRotation = Quaternion.Euler(270f, 180f, 0f);
                    node.AddComponent<Brick>();
                    node.GetComponent<Brick>().m_LightingCurve = brickPattern.m_LightingCurve;
                    node.renderer.material = Resources.Load("Bricks/Material/Brick") as Material;
                }
            }

            foreach (KeyValuePair<Transform, Dictionary<Vector3, int>> addCubePerLine in addCubes)
            {
                if (addCubePerLine.Value.Count > 0)
                {
                    foreach(KeyValuePair<Vector3,int> addCube in addCubePerLine.Value)
                    {
                        GameObject node = Instantiate(Resources.Load("Bricks/" + addCube.Value)) as GameObject;
                        node.transform.parent = addCubePerLine.Key;
                        node.transform.localPosition = addCube.Key;
                        node.transform.localRotation = Quaternion.Euler(270f, 180f, 0f);
                        node.AddComponent<Brick>();
                        node.GetComponent<Brick>().m_LightingCurve = brickPattern.m_LightingCurve;
                    }
                }
            }
        }
        GUILayout.EndHorizontal();
    }
}