using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Windows.Media.Imaging;
using System.Windows.Media;
using System.IO;

namespace GameRes.Formats.Kid
{
    [Export(typeof(ImageFormat))]
    public class LbgFormat : ImageFormat
    {
        public override string Tag { get { return "LBG/PS2-SPC"; } }
        public override string Description { get { return "KID PS2 SPC Image Format"; } }
        public override uint Signature { get { return 0; } } //real signature may exist below

        public LbgFormat()
        {
            Extensions = new string[] { "", "lbg" };
            // Actually LBG format can contain more than one image as lip for chara, well, "not implemented".
        }

        public override ImageMetaData ReadMetaData(IBinaryStream file)
        {
            uint header = file.ReadUInt32();
            uint overheader = 0;

            if (header != 0x2047424C) //LBG\x20
            {
                overheader = header;
                if (overheader > 0x50) //usually 10 or 30, never seen any larger
                    return null;
                file.Seek(overheader, SeekOrigin.Begin);
                header = file.ReadUInt32();
                if (header != 0x2047424C) //LBG\x20
                    return null;
            }

            int width = file.ReadInt16();
            int height = file.ReadInt16();
            if (width <= 0 || height <= 0)
                return null;

            return new LbgImageMetaData
            {
                Width = (uint)width,
                Height = (uint)height,
                OverHeader = overheader,
            };
        }
        public override ImageData Read(IBinaryStream file, ImageMetaData info)
        {
            if (info == null)
                throw new NotSupportedException(string.Format("Not LBG texture format."));

            /*if (info.Width != 640)
            {
                throw new NotSupportedException(string.Format("Not 640 pixels width, may not work."));
            }*/
            var lbgheader = (LbgImageMetaData)info;
            uint oversize = 0;
            uint blocknum = info.Width / 126;
            if (lbgheader.OverHeader != 0)
            {
                file.Position = 4;
                uint filesize = file.ReadUInt32();
                if (filesize == 0)
                    oversize = 8;
                else
                {
                    filesize -= 16;
                    oversize = (filesize - info.Width * info.Height * 4) / info.Height / (blocknum + 1);
                }
            }
            file.Position = lbgheader.OverHeader + 0x10;
            //List<byte> pixels = new List<byte>();
            byte[] pixels = new byte[info.Width * info.Height * 4];
            for (int blockcount = 0; blockcount <= blocknum; blockcount++)
            {
                for (int y = 0; y < info.Height; y++)
                {
                    for (int x = 0; (blockcount != blocknum & x < 126) | (blockcount == blocknum & x < info.Width - blockcount * 126); x++)
                    {
                        var pixel = file.ReadBytes(4); //RGBA with wrong A
                        long target = (x + blockcount * 126) * 4 + y * info.Width * 4;
                        //BGRA
                        pixels[target] = pixel[2];
                        pixels[target + 1] = pixel[1];
                        pixels[target + 2] = pixel[0];
                        if (pixel[3] >= byte.MaxValue / 2)
                            pixels[target + 3] = byte.MaxValue;
                        else
                            pixels[target + 3] = (byte)(pixel[3] << 1); //needs a test
                    }
                    if (oversize != 0)
                        file.ReadBytes((int)oversize);
                }
            }
            return ImageData.Create(info, PixelFormats.Bgra32, null, pixels);
        }

        public override void Write(Stream file, ImageData bitmap)
        {
            throw new NotImplementedException("LbgFormat.Write not implemented");
        }
    }
    class LbgImageMetaData : ImageMetaData
    {
        public uint OverHeader { get; set; }
    }
}