//+--------------------------------------------------------------------------+
//|                                                                          |
//|                             GDImage class                                |
//|                                                                          |
//+--------------------------------------------------------------------------+
//|                                                                          |
//|                         Author Patrice TERRIER                           |
//|                           copyright (c) 2006                             |
//|                                                                          |
//|                        pterrier@zapsolution.com                          |
//|                                                                          |
//|                          www.zapsolution.com                             |
//|                                                                          |
//+--------------------------------------------------------------------------+
//|                  Project started on : 10-17-2006 (MM-DD-YYYY)            |
//|                        Last revised : 10-25-2006 (MM-DD-YYYY)            |
//+--------------------------------------------------------------------------+

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

using System.Drawing;
using System.Windows.Forms;
using Win32;
using OpenGL;

namespace GDImage
{
    class GI
    {
        private const string GDIMAGE = @"gdimage.dll";

        public const string GDImageClassName = "ZIMAGECTRL";
        public const string GLImageClassName = "ZOPENGLCTRL";

        // ANCHOR properties
        public const int ANCHOR_NONE = 0;
        public const int ANCHOR_WIDTH = 1;
        public const int ANCHOR_RIGHT = 2;
        public const int ANCHOR_CENTER_HORZ = 3;
        public const int ANCHOR_HEIGHT = 4;
        public const int ANCHOR_HEIGHT_WIDTH = 5;
        public const int ANCHOR_HEIGHT_RIGHT = 6;
        public const int ANCHOR_BOTTOM = 7;
        public const int ANCHOR_BOTTOM_WIDTH = 8;
        public const int ANCHOR_BOTTOM_RIGHT = 9;
        public const int ANCHOR_CENTER_HORZ_BOTTOM = 10;
        public const int ANCHOR_CENTER_VERT = 11;
        public const int ANCHOR_CENTER_VERT_RIGHT = 12;
        public const int ANCHOR_CENTER = 13;

        // ZD_DrawText constants
        public const int ZD_TextHorzUp = 0x0;       // Horizontal text orientation
        public const int ZD_TextVertUp = 0x1;       // Vertical text orientation from bottom to top
        public const int ZD_TextVertDn = 0x2;       // Vertical text orientation from top to bottom
        public const int ZD_HIDE = 0x0;             // FALSE
        public const int ZD_SHOW = 0x1;             // TRUE

        public const int ZD_DRAW_REDRAW = -1;     // Forces immediat redraw of parent object
        public const int ZD_DRAW_DEFERRED = 0;      // Defers redraw of parent object

        // GDImage overlay Generic STYLE must be a 2^
        public const int ZS_HIDDEN = ZD_HIDE;
        public const int ZS_VISIBLE = ZD_SHOW;      // VISIBLE, same as WS_VISIBLE
        public const int ZS_SCROLL = 0x2;           // MOVE with scroll bars, default is FIX (do not scroll)
        public const int ZS_DRAFT = 0x4;            // Draft drawing mode

        public const int ZI_FitToWindow = 7;        // Resize the image to fit the view port
        // And use any of this constant as Parameter
        public const int ZI_QualityDefault = -1;
        public const int ZI_QualityGood = 1;        // Best performance
        public const int ZI_QualityHigh = 2;        // Best rendering quality

        public const int ZI_Horizontal = 3;         // Horizontal scrolling position
        public const int ZI_Vertical = 4;           // Vertical scrolling position
        public const int ZI_GradientTop = 5;        // Set/Get top gradiant color backgroud
        public const int ZI_GradientBottom = 6;     // Set/Get bottom gradiant color backgroud
        public const int ZI_ZoomWindow = 11;        // Set/Get zoom window status
        public const int ZI_Orientation = 13;       // Set/Get orientation 

        public const int RotateNoneFlipNone = 0;    // GDI+ constant
        public const int Rotate90FlipNone = 1;      // GDI+ constant
        public const int Rotate180FlipNone = 2;     // GDI+ constant
        public const int Rotate270FlipNone = 3;     // GDI+ constant
        public const int RotateNoneFlipX = 4;       // GDI+ constant
        public const int RotateNoneFlipY = 6;       // GDI+ constant

        [StructLayout(LayoutKind.Sequential)]
        public struct ZGLFONT
        {
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)]
            public string fontName; // The True Type font name.
            public int fontBase;    // The OpenGL FontBase (do not set this).
            public int charStart;   // OpenGL starting ASCII character (usually 32).
            public int charNum;     // OpenGL number of glyphe characters to create(usually 96).
            public int fontHeight;  // The font size (72 DPI).
            public int fontWeight;  // The font weigt.
            public int fontHandle;  // The Win32 font handle
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct ZGLTEXTURE
        {
            public int ID;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = Api.MAX_PATH)]
            public string FullName;
            public int Texture;
        }

        [DllImport(GDIMAGE, EntryPoint = "ZI_UseGLPolarView")]
        public static extern void UseGLPolarView(double radius, double twist, double latitude, double longitude);

        [DllImport(GDIMAGE, EntryPoint = "ZI_GetImageSizeFromFile")]
        public static extern int GetImageSizeFromFile(string FullPathName, out int width, out int height);

        [DllImport(GDIMAGE, EntryPoint = "ZI_UpdateNamedGLTextureFromFile")]
        public static extern int UpdateNamedGLTextureFromFile(string zFullName, int NamedTexture);

        [DllImport(GDIMAGE, EntryPoint = "ZI_CreateMultipleGLtextures")]
        public static extern int CreateMultipleGLtextures(ref ZGLTEXTURE[] mt, int n);

        [DllImport(GDIMAGE, EntryPoint = "ZI_CreateMultiple32BitGLtextures")]
        public static extern int CreateMultiple32BitGLtextures(ref ZGLTEXTURE[] mt, int n);

        //[DllImport(GDIMAGE, EntryPoint = "ZI_CreateGLTextureFrom32Bit")]
        //public static extern int CreateGLTextureFrom32Bit(string zFullPath, ref int xSize, ref int ySize, ref byte[] PixelArray);
        
        [DllImport(GDIMAGE, EntryPoint = "ZI_BuildGLfont")]
        public static extern void BuildGLfont(int hDC, ref ZGLFONT Font);

        [DllImport(GDIMAGE, EntryPoint = "ZI_DeleteGLFont")]
        public static extern void DeleteGLFont(ref ZGLFONT Font);

        [DllImport(GDIMAGE, EntryPoint = "ZI_DrawGLText")]
        public static extern void DrawGLText(IntPtr hWnd, ref ZGLFONT Font, int x, int y, string zTxt, int ARGB);

        [DllImport(GDIMAGE, EntryPoint = "ZI_GetGLzoom")]
        public static extern int ZI_GetGLzoom(IntPtr hWnd);

        [DllImport(GDIMAGE, EntryPoint = "ZI_GetGLDC")]
        public static extern int GetGLDC(IntPtr hWnd);

        [DllImport(GDIMAGE, EntryPoint = "ZI_GetGLzoom")]
        public static extern int GetGLzoom(IntPtr hWnd);

        [DllImport(GDIMAGE, EntryPoint = "ZI_SetGLzoom")]
        public static extern void SetGLzoom(IntPtr hWnd, int fovy);

        [DllImport(GDIMAGE)]  // Register the GDImage Win32 class
        public static extern bool RegisterGLImageClass();

        //[DllImport(GDIMAGE)]
        //public static extern int ZI_CreateGLTextureFromFile(string zFullPath, ref int xSize, ref int ySize, byte[] PixelArray);

        [DllImport(GDIMAGE, EntryPoint = "ZI_DoNotSquareTexture")]
        public static extern void DoNotSquareTexture();

        [DllImport(GDIMAGE, EntryPoint = "ZI_SetGLTextureFromFile")]
        public static extern int SetGLTextureFromFile(string zFullName);

        [DllImport(GDIMAGE)]  // Register the GDImage Win32 class
        public static extern bool RegisterGDImageClass();

        [DllImport(GDIMAGE)]  // Load image from file
        public static extern void ZI_SetFromFile(
        IntPtr hCtrl,       // The GDImage control
        string zFullPath    // The control unique IDentifier
        );

        [DllImport(GDIMAGE, EntryPoint = "ZI_InitGLControl")]
        public static extern void InitGLControl(int ARGB);

        [DllImport(GDIMAGE)]  // Anchor control to the main window form
        public static extern void ZI_SetAnchorMode(
        IntPtr hCtrl,       // The GDImage control
        int AnchorMode      // The control unique IDentifier
        );

        // Dialog file selector with thumbnail preview 
        [DllImport(GDIMAGE, EntryPoint = "ZI_LoadDialog")]
        public static extern string LoadDialog(
        IntPtr hParent      // The Window/Dialog container
        );

        [DllImport(GDIMAGE, EntryPoint = "ZI_LoadSavePath")]
        public static extern string LoadSavePath(string zUseThisPath, bool RW);

        // Set property of a GDImage control
        [DllImport(GDIMAGE, EntryPoint = "ZI_SetProperty")]
        public static extern void SetProperty(
        IntPtr hCtrl,       // The GDImage control
        int nProperty,      // A ZI_ predefined constant
        int nParam          // A parameter matching the type of property to set or retrieve.
        );

        // Get property of a GDImage control
        [DllImport(GDIMAGE, EntryPoint = "ZI_GetProperty")]
        public static extern int GetProperty(
        IntPtr hCtrl,       // The GDImage control
        int nProperty       // A ZI_ predefined constant
        );

        [DllImport(GDIMAGE)]  // Get the Device Context of a GDImage control
        public static extern int ZI_GetDC(
        IntPtr hCtrl        // The GDImage control
        );

        [DllImport(GDIMAGE)]  // Get width and height of a provide bitmap
        public static extern void ZI_GetBitmapSize(
        IntPtr hBitmap,     // Handle to a standard bitmap.
        out int Width,      // Width of the bitmap.
        out int Height      // Height of the bitmap.
        );

        [DllImport(GDIMAGE)]  // Load image from file and return a valid GDIPLUS image handle
        public static extern int zLoadImageFromFile(
        string zFullName,   // Full path name to any of the supported graphic format.
        out int imgW,       // Return the image width.
        out int imgH,       // Return the image height.
        int Orientation     // Orientation to create the memory image.
        );

        [DllImport(GDIMAGE)]  // Save image to file using a valid GDIPLUS image handle.
        public static extern int zSaveImageToFile(
        string zFullName,   // Full path name destination.
        int Img,            // A valid GDIPLUS handle.
        int Quality         // Quality applies to the JPEG format only. 
        );

        [DllImport(GDIMAGE)]  // Save image to file using a valid GDIPLUS image handle.
        public static extern int ZD_DrawTextToCtrl(
        IntPtr hCtrl,       // The GDImage control
        string zUseTex,     // The text to display.
        int x,              // Top left X coordinate.
        int y,              // Top left Y coordinate.
        uint ColrARGB,      // The ARGB color to use.
        string zUseFont,    // The "Tue Type Font" name to use.
        int UseSize,        // The size of the font in pixel.
        int ObjID,          // The unique object IDentifier (each object MUST USE A UNIQUE one).
        int ZS_STYLE,       // The object Generic STYLE (use at least ZS_VISIBLE to show it).
        int UseShadow,      // The shadow 3D offset.
        int Orientation     // The text orientation (%ZD_TextHorzUp, %ZD_TextVertUp, %ZD_TextVertDn).
        );

        [DllImport(GDIMAGE)]  // Save image to file using a valid GDIPLUS image handle.
        public static extern uint ZD_ColorARGB(
        byte AlphaChannel,  // The translucency level ranging from 0 to 255.
        int RGB             // The classical RGB() color to use.
        );

        [DllImport(GDIMAGE)]  // Create empty image background (Bitmap) into a GDImage control.
        public static extern int ZI_CreateImageBackground(
        IntPtr hCtrl,       // The GDImage control
        int Width,          // Width
        int Height          // Height
        );

        [DllImport(GDIMAGE)]  // Create a valid GDI BITMAP handle from FILE using any of the supported GDImage format.
        public static extern IntPtr ZI_CreateBitmapFromFile(
        string zFullName,   // Name of an image file.
        out int Width,      // Width of the bitmap.
        out int Height      // Height of the bitmap.
            // Return:
            // A valid GDI bitmap handle (do not confuse GDI bitmap handle and GDI+ Image handle).
            // Important:
            // You must use DeleteObject(GDIBitmapHandle) when you do not need it anymore.
        );

        [DllImport(GDIMAGE)]  // Create a sprite BITMAP.
        public static extern int ZD_DrawBitmapToCtrl(
        IntPtr hCtrl,       // The GDImage control
        int x, int y, IntPtr Bitmap, uint ColorARGB, int ID, int Style
        );

        [DllImport(GDIMAGE)]  // Create a sprite BITMAP.
        public static extern void ZD_SetObjectImageLabel(
        int ObjID,          // The unique sprite object identifier.
        string zlabel       // The label to use.
        );

        [DllImport(GDIMAGE)]  // Setup the scroll with background property of a specific sprite object.
        public static extern void ZD_SetObjectScroll(
        int ObjID,          // The unique sprite object identifier.
        Boolean TrueFalse   // The TRUE or FALSE scroll mode. 
            // Remark:
            // If scroll mode is set to false (default),
            // then the sprite looks floating above the backround when you scroll it.
        );

        [DllImport(GDIMAGE)]  // Use full variable opacity with 32-bit PNG transparent.
        public static extern void ZD_UsePngOpacity(
        int ObjID,          // The unique sprite object identifier.
        Boolean TrueFalse   // The TRUE or FALSE scroll mode. 
            // Remark:
            // Feature only available with PNG 32-bit, because they have an alpha channel.
        );

        [DllImport(GDIMAGE)]  // Get the current GDImage version #
        public static extern string ZI_Version();

        [DllImport(GDIMAGE)]  // Create a simplified GDImage control window
        public static extern IntPtr ZI_CreateWindow(
        IntPtr hParent,     // The Window/Dialog container
        int x,              // The control top left corner horizontal location
        int y,              // The control top left corner vertical location
        int xW,             // The control width
        int yH,             // The control height
        int ControlID       // The control unique IDentifier
        );

        [DllImport(GDIMAGE)]  // Retrieve the unique IDentifier of the sprite being moved.
        public static extern int ZI_GetMovingSpriteID();

        [DllImport(GDIMAGE)]  // Retrieve sprite overlay object X, Y coordinates
        public static extern void ZD_GetObjectXY(
        int ObjID,          // The unique sprite object identifier.
        out int x,          // The X coordinate
        out int y           // The Y coordinate
        );

        [DllImport(GDIMAGE)]  // Retrieve the GDImage mouse captured X,Y location.
        public static extern void ZD_GetObjectXYcapture(
        int ObjID,          // The unique sprite object identifier.
        out int x,          // The X coordinate
        out int y           // The Y coordinate
        );

        [DllImport(GDIMAGE)]  // Set the X,Y coordinates of an overlay object.
        public static extern void ZD_SetObjectXY(
        int ObjID,          // The unique object IDentifier (each object MUST USE A UNIQUE one)
        int x,              // The X coordinate
        int y,              // The Y coordinate
        int RedrawParent    // TRUE causes immediat redraw of the object parent
        );

        [DllImport(GDIMAGE)]  // Retrieve unique object IDentifier of the sprite hover the mouse.
        public static extern int ZI_MouseOverObjectID();

        [DllImport(GDIMAGE)]  // Retrieve the label matching a specific sprite object identifier.
        public static extern string ZD_GetObjectImageLabel(
        int ObjID           // The unique object IDentifier (each object MUST USE A UNIQUE one)
        );

        [DllImport(GDIMAGE)]  // Retrieve  bounding size that best fit sprite overlay region
        public static extern void ZD_GetObjectBound(
        int ObjID,          // The unique object IDentifier (each object MUST USE A UNIQUE one)
        out int BoundWidth, // Bounding Width
        out int BoundHeight // Bounding Height
        );

        [DllImport(GDIMAGE)]  // Force immediate refresh of a GDImage control display
        public static extern void ZI_UpdateWindow(
        IntPtr hCtrl,       // The GDImage control
        Boolean EraseFlag   // Boolean flag to erase first the background.
        );

        [DllImport(GDIMAGE)]  // Retrieve the DIB bitmap handle of the GDImage control background.
        public static extern IntPtr ZI_GetBMP(
        IntPtr hCtrl        // The GDImage control
        );

        [DllImport(GDIMAGE)]  // Retrieve the scroll status of a specific sprite object identifier.
        public static extern bool ZD_GetObjectScroll(
        int ObjID           // The unique object IDentifier (each object MUST USE A UNIQUE one)
        );

        [DllImport(GDIMAGE)]  // Retrieve the unique object IDentifier of the sprite that has the GDImage focus.
        public static extern int ZI_GetObjectFocusID();

        [DllImport(GDIMAGE)]  // Determines whether the Ctrl key is up or down at the time the function is called.
        public static extern bool ZI_IsCtrlKeyPressed();

        [DllImport(GDIMAGE)]  // Determines whether a the Shift key is up or down at the time the function is called.
        public static extern bool ZI_IsShiftKeyPressed();

        [DllImport(GDIMAGE)]  // Determines whether a the Alt key is up or down at the time the function is called.
        public static extern bool ZI_IsAltKeyPressed();

        [DllImport(GDIMAGE)]  // Determines whether a key is up or down at the time the function is called.
        public static extern bool ZI_IsKeyDown(
        int CheckKey        // One of 256 possible virtual-key codes.
        );

        [DllImport(GDIMAGE, EntryPoint = "ZI_IsLButtonDown")]  // Determines whether the left mouse button is up or down at the time the function is called.
        public static extern bool IsLButtonDown();

        [DllImport(GDIMAGE, EntryPoint = "ZI_IsRButtonDown")]  // Determines whether the right mouse button is up or down at the time the function is called.
        public static extern bool IsRButtonDown();

        [DllImport(GDIMAGE, EntryPoint = "ZI_UseGLPanoramaView")]
        public static extern void UseGLPanoramaView(double latitude, double longitude);

        [DllImport(GDIMAGE, EntryPoint = "ZI_UpdateGLWindow")]
        public static extern void UpdateGLWindow(IntPtr hCtrl);

        [DllImport(GDIMAGE, EntryPoint = "ZI_ResizeGLWindow")]
        public static extern void ResizeGLWindow(IntPtr hWnd);

        public static void CaptureDesktop(IntPtr hCtrl) // The GDImage control
        {
            int SysXRes = Screen.PrimaryScreen.Bounds.Width;
            int SysYRes = Screen.PrimaryScreen.Bounds.Height;
            GI.ZI_CreateImageBackground(hCtrl, SysXRes, SysYRes);
            int hDCDest = GI.ZI_GetDC(hCtrl);
            IntPtr hDeskTop = Api.GetDesktopWindow();
            int hDCSrce = Api.GetWindowDC(hDeskTop);
            Api.BitBlt(hDCDest, 0, 0, SysXRes, SysYRes, hDCSrce, 0, 0, Api.SRCCOPY);
            Api.ReleaseDC(hDeskTop, hDCSrce);
        }

        public static IntPtr CreateOpenGLWindow(IntPtr hParent, int x, int y, int xW, int yH, int ControlID)
        {
            IntPtr hWin = IntPtr.Zero;
            uint Style = Api.WS_CHILD | Api.WS_VISIBLE;
            uint StyleEx = Api.WS_EX_STATICEDGE;

            IntPtr Instance = Api.GetModuleHandle("");

            hWin = Api.CreateWindowEx(StyleEx,
                           GLImageClassName,   // window class name
                           "",                 // window title
                           Style,              // window style
                           x,                  // x location
                           y,                  // y location
                           xW,                 // Width
                           yH,                 // Height
                           hParent,            // parent window handle
                           ControlID,          // ControlID
                           Instance,           // program instance handle
                           0);                 // creation parameters
            return hWin;
        }

        public static IntPtr CreateGLcontrol(Control T, int ID)
        {
            System.IntPtr hCtrl;
            hCtrl = CreateOpenGLWindow(
                T.Parent.Handle,    // The Window/Dialog container
                T.Location.X,       // Horizontal location
                T.Location.Y,       // Vertical location
                T.Size.Width,       // Width
                T.Size.Height,      // Height
                ID);                // Unique IDentifier
            return hCtrl;
        }

        public static IntPtr CreateControl(Control T, int ID)
        {
            System.IntPtr hCtrl;
            hCtrl = ZI_CreateWindow(
                T.Parent.Handle,    // The Window/Dialog container
                T.Location.X,       // Horizontal location
                T.Location.Y,       // Vertical location
                T.Size.Width,       // Width
                T.Size.Height,      // Height
                ID);                // Unique IDentifier
            return hCtrl;
        }

        public static IntPtr CreateZoomControl(Control T, int ID)
        {
            System.IntPtr hCtrl = CreateControl(T, ID);
            GI.SetProperty(hCtrl, GI.ZI_ZoomWindow, -1);
            return hCtrl;
        }

        public static IntPtr CreateThumbControl(Control T, int ID)
        {
            System.IntPtr hCtrl = CreateControl(T, ID);
            GI.SetProperty(hCtrl, GI.ZI_FitToWindow, GI.ZI_QualityDefault);
            return hCtrl;
        }

    }
}
