using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;

namespace General
{
    class Tools
    {

        public static void WriteStringToStream(Stream s, String str)
        {
            Byte[] bytes = Encoding.UTF8.GetBytes(str);
            s.Write(bytes, 0x00, bytes.Length);
        }
        public static MemoryStream ByteToStream(byte[] Array)
        {
            MemoryStream ms = new MemoryStream();
            ms.Write(Array, 0x00, Array.Length);
            ms.Seek(0, SeekOrigin.Begin);
            return ms;
        }

        public static byte[] StreamToByte(Stream stream)
        {
            int StreamLen = (int)stream.Length;
            byte[] Bytes = new byte[StreamLen];
            stream.Seek(0, SeekOrigin.Begin);
            stream.Read(Bytes, 0x00, StreamLen);
            return Bytes;
        }

        public static string GetFileExtension(byte[] Bytes)
        {
            if (IsImage(Bytes))
            {
                return ".png";
            }
            else if (IsZlib(Bytes))
            {
                return ".zlib";
            }
            else if (IsRcf(Bytes))
            {
                return ".rcs";
            }
            else if (IsDDS(Bytes))
            {
                return ".dds";
            }
            else if (IsVAG(Bytes))
            {
                return ".vag";
            }
            else if (IsGim(Bytes))
            {
                return ".gim";
            }
            else
            {
                return ".bin";
            }
        }

        public static bool IsVAG(byte[] Bytes)
        {
            MemoryStream Data = ByteToStream(Bytes);
            String header = ReadString(Data, 4);
            if (header.StartsWith("VAG"))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public static bool IsDDS(byte[] Bytes)
        {
            MemoryStream Data = ByteToStream(Bytes);
            String header = ReadString(Data, 4);
            if (header.StartsWith("DDS"))
            {
                return true;
            }
            else
            {
                return false;
            }
        }


        public static bool IsRcf(byte[] Bytes)
        {
            MemoryStream Data = ByteToStream(Bytes);
            String header = ReadString(Data, 5);
            if (header.StartsWith("RCSF"))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public static bool IsGim(byte[] Bytes)
        {
            MemoryStream Data = ByteToStream(Bytes);
            String header = ReadString(Data, 4);
            if (header.StartsWith("MIG"))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public static bool IsZlib(byte[] Bytes)
        {
            if (Bytes[0] == 0x78)
            {
                if (Bytes[1] == 0x01)
                    return true;
                if (Bytes[1] == 0x9C)
                    return true;
                if (Bytes[1] == 0xDA)
                    return true;
            }
            return false;
        }



        public static bool IsImage(byte[] Bytes)
        {
            try
            {
                GetBitmap(Bytes);
            }
            catch (Exception)
            {
                return false;
            }
            return true;
        }

        public static Bitmap GetBitmap(byte[] BitmapBytes)
        {
            MemoryStream ms = ByteToStream(BitmapBytes);
            Bitmap bmp = new Bitmap(ms);
            ms.Dispose();
            return bmp;
        }

        public static String ReadStringAt(Stream ms, int location)
        {
            long ogPos = ms.Position;
            ms.Seek(location, SeekOrigin.Begin);
            String str = ReadString(ms);
            ms.Seek(ogPos, SeekOrigin.Begin);
            return str;
        }

        public static int ReadIntAt(Stream ms, int location)
        {
            BinaryReader BinReader = new BinaryReader(ms);
            long ogPos = ms.Position;
            ms.Seek(location, SeekOrigin.Begin);
            int i = BinReader.ReadInt32();
            ms.Seek(ogPos, SeekOrigin.Begin);
            return i;
        }

        public static int ReadInt(Stream ms)
        {
            BinaryReader BinReader = new BinaryReader(ms);
            int i = BinReader.ReadInt32();
            return i;
        }

        public static int ReadBigEndainIntAt(Stream ms, int location)
        {
            long ogPos = ms.Position;
            ms.Seek(location, SeekOrigin.Begin);
            int i = ReadBigEndainInt(ms);
            ms.Seek(ogPos, SeekOrigin.Begin);
            return i;
        }

        public static int ReadBigEndainInt(Stream ms)
        {
            byte[] IntBytes = new byte[4];
            ms.Read(IntBytes, 0x00, 4);
            IntBytes = IntBytes.Reverse().ToArray();
            int i = BitConverter.ToInt32(IntBytes, 0x00);
            return i;
        }

        public static String GenerateHash(byte[] Data)
        {
            SHA1 sha = SHA1.Create();
            byte[] ShaBytes = sha.ComputeHash(Data);
            int Hash = BitConverter.ToInt32(ShaBytes, 0);
            return Hash.ToString("X8");
        }

        public static String ReadString(Stream ms, int limit = -1)
        {
            int i = 0xFF;
            int counter = 0;

            MemoryStream StringStream = new MemoryStream();

            do
            {
                i = ms.ReadByte();
                if (i == 0 || counter == limit)
                    break;
                StringStream.WriteByte((byte)i);
                counter += 1;
            }
            while (true);

            byte[] StringData = StringStream.ToArray();

            String str = Encoding.UTF8.GetString(StringData);

            return str;

        }
    }

}
