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

public static class IOUtils
{
    public static byte[] readData;
    public static int readByteIndex;

    public static byte[] writeBuffer;
    public static int writeIndex;

    public static List<byte> writeData = new List<byte>();

    public static Dictionary<string, string[]> ReadDB(string filename, string searchLabel)
    {
        Dictionary<string, string[]> db = new Dictionary<string, string[]>();

        //Find the Text Asset Database file
        TextAsset asset = null;
        string filter = filename + " t:TextAsset l:" + searchLabel;
        string[] guids = AssetDatabase.FindAssets(filter);
        if (guids.Length > 0)
        {
            string assetPath = AssetDatabase.GUIDToAssetPath(guids[0]);
            asset = AssetDatabase.LoadAssetAtPath<TextAsset>(assetPath);
        }
        if (asset == null)
            return db;

        //Parse the text asset
        string[] lines = asset.text.Split("\n"[0]);
        for (int i = 0; i < lines.Length; i++)
        {
            int wordStartIndex = 0;
            string dbKey = "";
            List<string> dbValues = new List<string>();
            while (true)
            {
                wordStartIndex = lines[i].IndexOf('\"', wordStartIndex);
                if (wordStartIndex < 0)
                    break;
                wordStartIndex++;
                int wordEndIndex = lines[i].IndexOf('\"', wordStartIndex);
                if (wordEndIndex < 0)
                    break;
                string word = lines[i].Substring(wordStartIndex, wordEndIndex - wordStartIndex);
                //Debug.Log("wordStartIndex: " + wordStartIndex + " wordEndIndex: " + wordEndIndex + " word: " + word);
                if (string.IsNullOrEmpty(dbKey))
                {
                    dbKey = word;
                }
                else
                {
                    dbValues.Add(word);
                }
                wordStartIndex = wordEndIndex + 1;
            }
            if (!string.IsNullOrEmpty(dbKey) && dbValues.Count > 0)
            {
                if (db.ContainsKey(dbKey))
                {
                    Debug.Log(dbKey + "is already in the " + filename + " database");
                }
                else
                {
                    db.Add(dbKey, dbValues.ToArray());
                }
            }
        }
        return db;
    }

    public static void WriteInt32(int value)
    {
        byte[] bytes = BitConverter.GetBytes(value);
        Array.Copy(bytes, 0, writeBuffer, writeIndex, bytes.Length);
        writeIndex += bytes.Length;
    }

    public static void WriteUInt32(uint value)
    {
        byte[] bytes = BitConverter.GetBytes(value);
        Array.Copy(bytes, 0, writeBuffer, writeIndex, bytes.Length);
        writeIndex += bytes.Length;
    }

    public static void WriteInt16(short value)
    {
        byte[] bytes = BitConverter.GetBytes(value);
        Array.Copy(bytes, 0, writeBuffer, writeIndex, bytes.Length);
        writeIndex += bytes.Length;
    }

    public static void WriteUInt16(ushort value)
    {
        byte[] bytes = BitConverter.GetBytes(value);
        Array.Copy(bytes, 0, writeBuffer, writeIndex, bytes.Length);
        writeIndex += bytes.Length;
    }

    public static void WriteSByte(sbyte value)
    {
        writeBuffer[writeIndex] = (byte)value;
        writeIndex++;
    }

    public static void WriteByte(byte value)
    {
        writeBuffer[writeIndex] = value;
        writeIndex++;
    }

    public static void WriteBytes(byte[] bytes)
    {
        Array.Copy(bytes, 0, writeBuffer, writeIndex, bytes.Length);
        writeIndex += bytes.Length;
    }

    public static void WriteColor(Color32 value)
    {
        WriteByte(value.r);
        WriteByte(value.g);
        WriteByte(value.b);
        WriteByte(value.a);
    }

    public static void WriteColorf(Color value)
    {
        WriteFloat(value.r);
        WriteFloat(value.g);
        WriteFloat(value.b);
        WriteFloat(value.a);
    }

    public static void WriteFloat(float value)
    {
        byte[] bytes = BitConverter.GetBytes(value);
        Array.Copy(bytes, 0, writeBuffer, writeIndex, bytes.Length);
        writeIndex += bytes.Length;
    }

    public static void WriteString(string value)
    {
        byte[] bytes = Encoding.ASCII.GetBytes(value + "\0");
        Array.Copy(bytes, 0, writeBuffer, writeIndex, bytes.Length);
        writeIndex += bytes.Length;
    }

    public static void WriteVector2(Vector2 value)
    {
        WriteFloat(value.x);
        WriteFloat(value.y);
    }

    public static void WriteVector3(Vector3 value)
    {
        WriteFloat(value.x);
        WriteFloat(value.y);
        WriteFloat(value.z);
    }

    public static void WriteVector4(Vector4 value)
    {
        WriteFloat(value.x);
        WriteFloat(value.y);
        WriteFloat(value.z);
        WriteFloat(value.w);
    }

    public static void WriteQuaternion(Quaternion value)
    {
        WriteFloat(value.x);
        WriteFloat(value.y);
        WriteFloat(value.z);
        WriteFloat(value.w);
    }

    public static void WriteListInt32(int value)
    {
        writeData.AddRange(BitConverter.GetBytes(value));
    }

    public static void WriteListUInt32(uint value)
    {
        writeData.AddRange(BitConverter.GetBytes(value));
    }

    public static void WriteListInt16(Int16 value)
    {
        writeData.AddRange(BitConverter.GetBytes(value));
    }

    public static void WriteListUInt16(UInt16 value)
    {
        writeData.AddRange(BitConverter.GetBytes(value));
    }

    public static void WriteListSByte(sbyte value)
    {
        writeData.Add((byte)value);
    }

    public static void WriteListByte(byte value)
    {
        writeData.Add(value);
    }

    public static void WriteListColor(Color32 color)
    {
        writeData.Add(color.r);
        writeData.Add(color.g);
        writeData.Add(color.b);
        writeData.Add(color.a);
    }

    public static void WriteListFloat(float value)
    {
        writeData.AddRange(BitConverter.GetBytes(value));
    }

    public static void WriteListString(string value)
    {
        byte[] data = Encoding.ASCII.GetBytes(value + "\0");
        writeData.AddRange(data);
    }

    public static void WriteListVector2(Vector2 value)
    {
        WriteListFloat(value.x);
        WriteListFloat(value.y);
    }

    public static void WriteListVector3(Vector3 value)
    {
        WriteListFloat(value.x);
        WriteListFloat(value.y);
        WriteListFloat(value.z);
    }

    public static void WriteListVector4(Vector4 value)
    {
        WriteListFloat(value.x);
        WriteListFloat(value.y);
        WriteListFloat(value.z);
        WriteListFloat(value.w);
    }

    public static int ReadInt32()
    {
        int result = BitConverter.ToInt32(readData, readByteIndex);
        readByteIndex += 4;
        return result;
    }

    public static uint ReadUInt32()
    {
        uint result = BitConverter.ToUInt32(readData, readByteIndex);
        readByteIndex += 4;
        return result;
    }

    public static Int16 ReadInt16()
    {
        Int16 result = BitConverter.ToInt16(readData, readByteIndex);
        readByteIndex += 2;
        return result;
    }

    public static UInt16 ReadUInt16()
    {
        UInt16 result = BitConverter.ToUInt16(readData, readByteIndex);
        readByteIndex += 2;
        return result;
    }

    public static sbyte ReadSByte()
    {
        sbyte result = unchecked((sbyte)readData[readByteIndex]);
        //sbyte result = Convert.ToSByte(readData[readByteIndex]);
        readByteIndex += 1;
        return result;
    }

    public static byte ReadByte()
    {
        byte result = readData[readByteIndex];
        readByteIndex += 1;
        return result;
    }

    public static void ReadBytes(int length, out byte[] dest)
    {
        dest = new byte[length];
        Array.Copy(readData, readByteIndex, dest, 0, length);
    }

    public static Color32 ReadColor()
    {
        Color32 result = new Color32(readData[readByteIndex], readData[readByteIndex+1], readData[readByteIndex+2], readData[readByteIndex+3]);
        readByteIndex += 4;
        return result;
    }

    public static Color ReadColorf()
    {
        float r = ReadFloat();
        float g = ReadFloat();
        float b = ReadFloat();
        float a = ReadFloat();

        return new Color(r, g, b, a);
    }

    public static float ReadFloat()
    {
        float result = BitConverter.ToSingle(readData, readByteIndex);
        readByteIndex += 4;
        return result;
    }

    public static string ReadString()
    {
        string result = "";
        byte b;
        while (true)
        {
            b = readData[readByteIndex];
            readByteIndex += 1;
            if (b == 0)
            {
                break;
            }
            result += Convert.ToChar(b);
        }

        return result;
    }

    public static string ReadString(int count)
    {
        string result = "";
        byte b;
        for (int i = 0; i < count; i++)
        {
            b = readData[readByteIndex];
            readByteIndex += 1;
            result += Convert.ToChar(b);
        }
        return result;
    }

    public static Vector2 ReadVector2()
    {
        float x = ReadFloat();
        float y = ReadFloat();
        return new Vector2(x, y);
    }

    public static Vector3 ReadVector3()
    {
        float x = ReadFloat();
        float y = ReadFloat();
        float z = ReadFloat();
        return new Vector3(x, y, z);
    }

    public static Vector4 ReadVector4()
    {
        float x = ReadFloat();
        float y = ReadFloat();
        float z = ReadFloat();
        float w = ReadFloat();
        return new Vector4(x, y, z, w);
    }

    public static Quaternion ReadQuaternion()
    {
        float x = ReadFloat();
        float y = ReadFloat();
        float z = ReadFloat();
        float w = ReadFloat();
        return new Quaternion(x, y, z, w);
    }
}
