using System;
using System.Runtime.InteropServices;

namespace Quik.FreeType
{
    public struct FTLibrary
    {
        private IntPtr _handle;
        public IntPtr Handle => _handle;
    }

    public unsafe struct FTFace
    {
        private IntPtr _handle;
        public IntPtr Handle => _handle;
        private unsafe FTFaceInternal* Ptr => (FTFaceInternal*)_handle;

        public long NumberOfGlyphs => Ptr->NumberOfGlyphs;
        public long FaceIndex => Ptr->FaceIndex;
        public FaceFlag FaceFlags => (FaceFlag)Ptr->FaceFlags;
        public long StyleFlags => Ptr->StyleFlags;
        public string FamilyName => Marshal.PtrToStringUTF8(Ptr->FamilyName);
        public string StyleName => Marshal.PtrToStringUTF8(Ptr->StyleName);
        public int NumberOfFixedSizes => Ptr->NumberOfFixedSizes;
        public int NumberOfCharMaps => Ptr->NumberOfCharMaps;
        public FTGlyphSlot Glyph => Ptr->Glyph;
        public short Ascender => Ptr->Ascender;
        public short Descender => Ptr->Descender;
        public ref readonly FTSizeMetrics ScaledSize => ref ((FTSize*)Ptr->Size)->Metrics;
    }

    public struct FTBox
    {
        public long XMin;
        public long YMin;
        public long XMax;
        public long YMax;
    }

    internal struct FTFaceInternal
    {
        public long NumberOfFaces;
        public long FaceIndex;
        public long FaceFlags;
        public long StyleFlags;
        public long NumberOfGlyphs;
        public IntPtr FamilyName;
        public IntPtr StyleName;
        public int NumberOfFixedSizes;
        public IntPtr AvailableSizes;
        public int NumberOfCharMaps;
        public IntPtr Charmaps;
        public FTGeneric Generic;
        public FTBox BoundingBox;
        public ushort UnitsPerEm;
        public short Ascender;
        public short Descender;
        public short Height;
        public short MaxAdvanceWidth;
        public short MaxAdvanceHeight;
        public short UnderlinePosition;
        public short UnderlineThickness;
        public FTGlyphSlot Glyph;
        public IntPtr Size;
        public IntPtr Charmap;

        // Rest of the struct is private to implementation.
    }

    public struct FTGeneric
    {
        public IntPtr Data;
        public IntPtr Finalizer;
    }

    public struct FTVector
    {
        public long X;
        public long Y;
    }

    public struct FTBitmap
    {
        public uint Rows;
        public uint Width;
        public int Pitch;
        public IntPtr Buffer;
        public ushort NumberOfGrays;
        public byte PixelMode;
        public byte PaletteMode;
        public IntPtr Palette;
    }

    public struct FTOutline
    {
        public short NumberOfContours;
        public short NumberOfPoints;
        public IntPtr Points;
        public IntPtr Tags;
        public IntPtr Contours;
        public int Flags;
    }

    internal struct FTGlyphSlotInternal
    {
        public FTLibrary Library;
        public FTFace Face;
        public FTGlyphSlot Next;
        public uint GlyphIndex;
        public FTGeneric Generic;
        public FTGlyphMetrics Metrics;
        public long LinearHorizontalAdvance;
        public long LinearVerticalAdvance;
        public FTVector Advance;
        public int Format;
        public FTBitmap Bitmap;
        public int BitmapLeft;
        public int BitmapTop;
        public FTOutline Outline;
        public uint NumberOfSubGlyphs;
        public IntPtr SubGlyphs;
        public IntPtr ControlData;
        public long ControlLength;
        public long LsbDelta;
        public long RsbDelta;
        public IntPtr Other;
        public IntPtr Internal;
    }

    public unsafe struct FTGlyphSlot
    {
        private IntPtr _handle;
        public IntPtr Handle => _handle;
        private FTGlyphSlotInternal* Ptr => (FTGlyphSlotInternal*) _handle;

        public FTLibrary Library => Ptr->Library;
        public FTFace Face => Ptr->Face;
        public FTGlyphSlot Next => Ptr->Next;
        public uint GlyphIndex => Ptr->GlyphIndex;
        public ref readonly FTGlyphMetrics Metrics => ref Ptr->Metrics;
        public long LinearHorizontalAdvance => Ptr->LinearHorizontalAdvance;
        public long LinearVerticalAdvance => Ptr->LinearVerticalAdvance;
        public FTVector Advance => Ptr->Advance;
        public ref readonly FTBitmap Bitmap => ref Ptr->Bitmap;
        public long BitmapLeft => Ptr->BitmapLeft;
        public long BitmapTop => Ptr->BitmapTop;
    }

    public struct FTGlyphMetrics
    {
        public long Width;
        public long Height;
        public long HorizontalBearingX;
        public long HorizontalBearingY;
        public long HorizontalAdvance;
        public long VerticalBearingX;
        public long VerticalBearingY;
        public long VerticalAdvance;
    }

    public struct FTSizeMetrics
    {
        public short Xppem;
        public short Yppem;
        public long XScale;
        public long YScale;
        public long Ascender;
        public long Descender;
        public long Height;
        public long MaxAdvance;
    }

    public struct FTSize
    {
        public IntPtr Face;
        public FTGeneric Generic;
        public FTSizeMetrics Metrics;
        private IntPtr Privates;
    }
}