using PathEditor.Proxy.Editor;
using System;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;

namespace Thousandto.DIY.UniScene
{
    public class PathGridDataFileChangeEditor : EditorWindow
    {
        [MenuItem("Ares/阻挡数据临时数据转换工具")]
        public static void Open()
        {
            var win = (PathGridDataFileChangeEditor)EditorWindow.GetWindow(typeof(PathGridDataFileChangeEditor));
            win.Show();
        }

        private string _filePath = string.Empty;
        private void OnGUI()
        {
            EditorGUILayout.BeginVertical();
            if (GUILayout.Button("选择文件"))
            {
                _filePath = EditorUtility.OpenFilePanel("Select Cover File", "Assets/GameAssets/Resources/MapInfo", "bytes");
            }

            GUILayout.Label(_filePath);

            if (GUILayout.Button("转换"))
            {
                Covert(_filePath);
            }
            if (GUILayout.Button("选择文件夹"))
            {
                _filePath = EditorUtility.OpenFolderPanel("Select Cover File", "Assets/GameAssets/Resources/MapInfo", "");
            }

            GUILayout.Label(_filePath);
            if (GUILayout.Button("转换"))
            {
                if (Directory.Exists(_filePath))
                {
                    DirectoryInfo direction = new DirectoryInfo(_filePath);
                    FileInfo[] files = direction.GetFiles("*_PathGrid.bytes", SearchOption.AllDirectories);
                    for (int i = 0; i < files.Length; ++i)
                    {
                        var path = files[i].FullName;
                        Conert2(path);
                    }
                }
            }

            EditorGUILayout.EndVertical();
        }

        public static Byte[] TAG = new Byte[4] { (Byte)'P', (Byte)'A', (Byte)'T', (Byte)'H' };
        private void Covert(string file)
        {
            FileStream fs = null;
            try
            {
                fs = new FileStream(file, FileMode.Open, FileAccess.Read);
                var r = new BinaryReader(fs);
                Byte[] tag = r.ReadBytes(4);
                if (tag.Equals(TAG))
                {
                    return;
                }
                r.ReadInt32();
                r.ReadInt32();
                r.ReadInt32();
                byte[] s = r.ReadBytes(60);
                var levelName = System.Text.Encoding.UTF8.GetString(s);
                var weightRadius = r.ReadInt32();
                var numberOfColumns = r.ReadInt32();
                var numberOfRows = r.ReadInt32();
                var cellSize = r.ReadSingle();
                var position = new Vector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle());
                var heightRangeLimit = new Vector2(r.ReadSingle(), r.ReadSingle());
                int mergeDataOffset = r.ReadInt32();
                int heightMapDataOffset = r.ReadInt32();
                int weightMergeDataOffset = r.ReadInt32();
                int mergeDataLength = r.ReadInt32();
                int heightMapDataLength = r.ReadInt32();
                int mergeWeightDataLength = r.ReadInt32();
                int num = numberOfRows * numberOfColumns;
                int num4 = num * 4;
                r.BaseStream.Seek(mergeDataOffset, SeekOrigin.Begin);
                Byte[] raw_mergedData = r.ReadBytes(num);
                r.BaseStream.Seek(heightMapDataOffset, SeekOrigin.Begin);
                Byte[] raw_heightMap = r.ReadBytes(num4);

                Byte[] raw_mergeWeightData = null;
                if (mergeWeightDataLength > 0)
                {
                    r.BaseStream.Seek(weightMergeDataOffset, SeekOrigin.Begin);
                    raw_mergeWeightData = r.ReadBytes(num);
                }

                var mergedData = new Byte[numberOfRows, numberOfColumns];
                int ptr = 0;
                for (int j = 0; j < numberOfRows; ++j)
                {
                    for (int i = 0; i < numberOfColumns; ++i)
                    {
                        mergedData[j, i] = raw_mergedData[ptr++];
                    }
                }

                var heightMap = new float[numberOfRows, numberOfColumns];
                int ptr2 = 0;
                unsafe
                {
                    for (int j = 0; j < numberOfRows; ++j)
                    {
                        for (int i = 0; i < numberOfColumns; ++i)
                        {
                            fixed (float* v = &heightMap[j, i])
                            {
                                byte* p = (byte*)v;
                                p[0] = raw_heightMap[ptr2];
                                p[1] = raw_heightMap[ptr2 + 1];
                                p[2] = raw_heightMap[ptr2 + 2];
                                p[3] = raw_heightMap[ptr2 + 3];
                            }
                            ptr2 += 4;
                        }
                    }
                }
                int ptr5 = 0;
                var mergeWeightData = new Byte[numberOfRows, numberOfColumns];
                for (int j = 0; j < numberOfRows; ++j)
                {
                    for (int i = 0; i < numberOfColumns; ++i)
                    {
                        mergeWeightData[j, i] = raw_mergeWeightData[ptr5++];
                    }
                }

                fs.Close();
                fs = new FileStream(file, FileMode.Truncate, FileAccess.Write);
                var w = new BinaryWriter(fs);
                fs.Seek(0, SeekOrigin.Begin);
                fs.Flush();
                w.Write(levelName.Length);
                w.Write(levelName.ToCharArray());
                w.Write(weightRadius);
                w.Write(numberOfColumns);
                w.Write(numberOfRows);
                w.Write(cellSize);
                w.Write(position.x);
                w.Write(position.y);
                w.Write(position.z);
                w.Write(heightRangeLimit.x);
                w.Write(heightRangeLimit.y);

                {
                    var coutList = new List<ushort>();
                    var valueList = new List<Byte>();

                    ushort curCount = 0;
                    Byte curValue = 0;
                    int allCount = 0;
                    for (int j = 0; j < numberOfRows; ++j)
                    {
                        for (int i = 0; i < numberOfColumns; ++i)
                        {
                            var tvalue = mergedData[j, i];
                            if (j == 0 && i == 0)
                            {
                                curValue = tvalue;
                            }

                            if (curValue == tvalue && curCount < ushort.MaxValue)
                            {
                                ++curCount;
                            }
                            else
                            {
                                allCount += curCount;
                                coutList.Add(curCount);
                                valueList.Add(curValue);

                                curValue = tvalue;
                                curCount = 1;
                            }
                        }
                    }
                    allCount += curCount;
                    coutList.Add(curCount);
                    valueList.Add(curValue);

                    w.Write(coutList.Count);
                    for (int i = 0; i < coutList.Count; ++i)
                    {
                        w.Write(coutList[i]);
                        w.Write(valueList[i]);
                    }
                }

                for (int j = 0; j < numberOfRows; ++j)
                {
                    for (int i = 0; i < numberOfColumns; ++i)
                    {
                        ushort height = (ushort)(heightMap[j, i] * 100f);
                        w.Write(height);
                    }
                }

                {
                    //重新计算权重
                    for (int j = 0; j < numberOfRows; ++j)
                    {
                        for (int i = 0; i < numberOfColumns; ++i)
                        {
                            byte weight = 0;
                            int nStartRowPos = j - weightRadius;
                            int nStartColumnPos = i - weightRadius;
                            int nEndRowPos = j + weightRadius;
                            int nEndColumnPos = i + weightRadius;

                            for (int k = nStartRowPos; k <= nEndRowPos; k++)
                            {
                                for (int l = nStartColumnPos; l <= nEndColumnPos; l++)
                                {
                                    if (k != j || l != i)
                                    {
                                        if (k < 0 || l < 0 || k >= numberOfRows || l >= numberOfColumns)
                                        {

                                        }
                                        else
                                        {
                                            if (mergedData[k, l] != 1 &&
                                                mergedData[k, l] != 2 &&
                                                mergedData[k, l] != 10)
                                            {
                                                ++weight;
                                            }
                                        }
                                    }
                                }
                            }
                            mergeWeightData[j, i] = weight;
                        }
                    }

                    var coutList = new List<ushort>();
                    var valueList = new List<Byte>();

                    ushort curCount = 0;
                    Byte curValue = 0;
                    int allCount = 0;

                    for (int j = 0; j < numberOfRows; ++j)
                    {
                        for (int i = 0; i < numberOfColumns; ++i)
                        {
                            var tvalue = mergeWeightData[j, i];
                            if (j == 0 && i == 0)
                            {
                                curValue = tvalue;
                            }

                            if (curValue == tvalue && curCount < ushort.MaxValue)
                            {
                                ++curCount;
                            }
                            else
                            {
                                allCount += curCount;
                                coutList.Add(curCount);
                                valueList.Add(curValue);

                                curValue = tvalue;
                                curCount = 1;
                            }
                        }
                    }

                    allCount += curCount;
                    coutList.Add(curCount);
                    valueList.Add(curValue);

                    w.Write(coutList.Count);
                    for (int i = 0; i < coutList.Count; ++i)
                    {
                        w.Write(coutList[i]);
                        w.Write(valueList[i]);
                    }
                }
            }
            catch (IOException e)
            {
                Debug.Log("Load PathGrid file failed: " + e.ToString());
            }
            finally
            {
                if (fs != null)
                {
                    fs.Close();
                }
            }
        }


        private void Conert2(string file)
        {
            FileStream fs = null;
            try
            {
                fs = new FileStream(file, FileMode.Open, FileAccess.Read);
                var r = new BinaryReader(fs);

                var LevelName = r.ReadString();
                var WeightRadius = r.ReadInt32();
                var NumberOfColumns = r.ReadInt32();
                var NumberOfRows = r.ReadInt32();
                var CellSize = r.ReadSingle();
                var Position = new Vector3(r.ReadSingle(), r.ReadSingle(), r.ReadSingle());
                var HeightRangeLimit = new Vector2(r.ReadSingle(), r.ReadSingle());

                int listCount = r.ReadInt32();
                var MergedData = new PathGridType[NumberOfRows, NumberOfColumns];
                int counter = 0;
                for (int i = 0; i < listCount; ++i)
                {
                    var curCount = r.ReadUInt16();
                    var curValue = r.ReadByte();

                    for (int j = counter; j < (counter + curCount); ++j)
                    {
                        int row = j / NumberOfColumns;
                        int col = j % NumberOfColumns;
                        MergedData[row, col] = (PathGridType)curValue;
                    }
                    counter += curCount;
                }

                var HeightMap = new float[NumberOfRows, NumberOfColumns];
                for (int j = 0; j < NumberOfRows; ++j)
                {
                    for (int i = 0; i < NumberOfColumns; ++i)
                    {
                        var tHeight = r.ReadUInt16();
                        HeightMap[j, i] = tHeight / 100f;
                    }
                }

                listCount = r.ReadInt32();
                var MergeWeightData = new byte[NumberOfRows, NumberOfColumns];
                counter = 0;
                for (int i = 0; i < listCount; ++i)
                {
                    var curCount = r.ReadUInt16();
                    var curValue = r.ReadByte();

                    for (int j = counter; j < (counter + curCount); ++j)
                    {
                        int row = j / NumberOfColumns;
                        int col = j % NumberOfColumns;
                        MergeWeightData[row, col] = curValue;
                    }
                    counter += curCount;
                }

                fs.Close();

                fs = new FileStream(file, FileMode.Truncate, FileAccess.Write);
                var w = new BinaryWriter(fs);
                fs.Seek(0, SeekOrigin.Begin);
                fs.Flush();
                w.Write(LevelName.Length);
                w.Write(LevelName.ToCharArray());
                w.Write(WeightRadius);
                w.Write(NumberOfColumns);
                w.Write(NumberOfRows);
                w.Write(CellSize);
                w.Write(Position.x);
                w.Write(Position.y);
                w.Write(Position.z);
                w.Write(HeightRangeLimit.x);
                w.Write(HeightRangeLimit.y);

                {
                    var coutList = new List<ushort>();
                    var valueList = new List<PathGridType>();

                    ushort curCount = 0;
                    PathGridType curValue = 0;
                    int allCount = 0;
                    for (int j = 0; j < NumberOfRows; ++j)
                    {
                        for (int i = 0; i < NumberOfColumns; ++i)
                        {
                            var tvalue = MergedData[j, i];
                            if (j == 0 && i == 0)
                            {
                                curValue = tvalue;
                            }

                            if (curValue == tvalue && curCount < ushort.MaxValue)
                            {
                                ++curCount;
                            }
                            else
                            {
                                allCount += curCount;
                                coutList.Add(curCount);
                                valueList.Add(curValue);

                                curValue = tvalue;
                                curCount = 1;
                            }
                        }
                    }
                    allCount += curCount;
                    coutList.Add(curCount);
                    valueList.Add(curValue);

                    w.Write(coutList.Count);
                    for (int i = 0; i < coutList.Count; ++i)
                    {
                        w.Write(coutList[i]);
                        w.Write((byte)valueList[i]);
                    }
                }

                for (int j = 0; j < NumberOfRows; ++j)
                {
                    for (int i = 0; i < NumberOfColumns; ++i)
                    {
                        ushort height = (ushort)(HeightMap[j, i] * 100f);
                        w.Write(height);
                    }
                }

                {
                    var coutList = new List<ushort>();
                    var valueList = new List<Byte>();

                    ushort curCount = 0;
                    byte curValue = 0;
                    int allCount = 0;

                    for (int j = 0; j < NumberOfRows; ++j)
                    {
                        for (int i = 0; i < NumberOfColumns; ++i)
                        {
                            var tvalue = MergeWeightData[j, i];
                            if (j == 0 && i == 0)
                            {
                                curValue = tvalue;
                            }

                            if (curValue == tvalue && curCount < ushort.MaxValue)
                            {
                                ++curCount;
                            }
                            else
                            {
                                allCount += curCount;
                                coutList.Add(curCount);
                                valueList.Add(curValue);

                                curValue = tvalue;
                                curCount = 1;
                            }
                        }
                    }

                    allCount += curCount;
                    coutList.Add(curCount);
                    valueList.Add(curValue);

                    w.Write(coutList.Count);
                    for (int i = 0; i < coutList.Count; ++i)
                    {
                        w.Write(coutList[i]);
                        w.Write(valueList[i]);
                    }
                }
            }
            finally
            {
                fs.Close();
            }
        }
    }
}