/**************************************************************************
 *   Copyright (C) 2010 by David S. Register                               *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, see <https://www.gnu.org/licenses/>. *
 **************************************************************************/

/**
 * \file
 *
 * Optimized wxBitmap Object
 */

#ifndef _OCPN_PIXEL_H_
#define _OCPN_PIXEL_H_

wxImage Image_Rotate(wxImage &base_image, double angle,
                     const wxPoint &centre_of_rotation, bool interpolating,
                     wxPoint *offset_after_rotation);

//--------------------------------------------------------------------------
//      Set the desired compile time conditionals related to display
//      optimization
//--------------------------------------------------------------------------

//          Specify the Pixel Cache type
//          Only one of the following must be selected
//          with due regard for the system type

// #define __PIX_CACHE_WXIMAGE__                               // a safe default
// #define __PIX_CACHE_DIBSECTION__                            // for MSW
// #define __PIX_CACHE_X11IMAGE__                              // for
// X11/Universal, requires ocpnUSE_ocpnBitmap

//  I use these shortcuts....
#ifdef __WXX11__
#define __PIX_CACHE_WXIMAGE__
// #define     __PIX_CACHE_X11IMAGE__
#endif

#ifdef __WXGTK__
#define __PIX_CACHE_WXIMAGE__
// #define     __PIX_CACHE_X11IMAGE__
// #define __PIX_CACHE_PIXBUF__
#endif

#ifdef __WXMSW__
#define __PIX_CACHE_WXIMAGE__
// #define __PIX_CACHE_DIBSECTION__
// #define     ocpnUSE_DIBSECTION
// #define     ocpnUSE_ocpnBitmap
#endif

#ifdef __WXOSX__
#define __PIX_CACHE_WXIMAGE__
#endif

#ifdef __WXQT__
#define __PIX_CACHE_WXIMAGE__
#endif

//    Some configuration sanity checks

//          Use ocpnBitmap (Optimized wxBitmap)
//          Required for X11 native systems, optional on MSW
//          Also required for GTK PixBuf optimized configuration

#ifdef __PIX_CACHE_X11IMAGE__
#define ocpnUSE_ocpnBitmap
#endif

#ifdef __PIX_CACHE_PIXBUF__
#define ocpnUSE_ocpnBitmap
#define opcnUSE_GTK_OPTIMIZE
#endif

//          For Optimized X11 systems, use MIT shared memory XImage, requires
//          ocpnUSE_ocpnBitmap
#ifdef __PIX_CACHE_X11IMAGE__
#define ocpUSE_MITSHM
#endif

//          The BitsPerPixel value for chart data storage
//          Todo get this during pixcache ctor
#ifdef __PIX_CACHE_WXIMAGE__  // a safe default
#define BPP 24
#endif
#ifdef __PIX_CACHE_DIBSECTION__  // for MSW
#define BPP 24
#endif
#ifdef __PIX_CACHE_X11IMAGE__  // for X11/Universal
#define BPP 32
#endif
#ifdef __PIX_CACHE_PIXBUF__  // for GTK Optimized
#define BPP 32
#endif

//    A fall back position is smart....
#ifndef BPP
#define BPP 24
#endif

//      Extended includes
#ifdef __PIX_CACHE_X11IMAGE__
#include <wx/x11/private.h>

//    For MIT-SHM Extensions
#include <sys/ipc.h>
#include <sys/shm.h>
#include <X11/extensions/XShm.h>
#endif

#ifdef __WXMSW__
#include <wx/msw/dib.h>  // for ocpnMemDC
#endif

// ============================================================================
// Declarations
// ============================================================================

typedef enum RGBO { RGB = 0, BGR } _RGBO;

class ocpnBitmap;  // forward in .cpp file

#ifdef __PIX_CACHE_X11IMAGE__
//----------------------------------------------------------------------
//      ocpnXImage Definition
//----------------------------------------------------------------------
class ocpnXImage {
public:
  ocpnXImage(int width, int height);
  ~ocpnXImage();
  bool PutImage(Pixmap pixmap, GC gc);

  bool buse_mit;
  XShmSegmentInfo shminfo;
  XImage *m_img;
  Display *xdisplay;
  int xscreen;
  Visual *xvisual;
  int bpp;
  int m_width, m_height;
};
#endif

// ============================================================================
// PixelCache Definition
// ============================================================================
class PixelCache {
public:
  //    Constructors

  PixelCache(int width, int height, int depth);
  ~PixelCache();

  void SelectIntoDC(wxMemoryDC &dc);
  void Update(void);
  RGBO GetRGBO() { return m_rgbo; }
  unsigned char *GetpData() const;
  int GetLinePitch() const { return line_pitch_bytes; }
  int GetWidth(void) { return m_width; }
  int GetHeight(void) { return m_height; }
  size_t GetLength(void);

  //    Data storage
private:
  int m_width;
  int m_height;
  int m_depth;
  int line_pitch_bytes;
  int bytes_per_pixel;
  RGBO m_rgbo;
  unsigned char *pData;

#ifdef ocpnUSE_ocpnBitmap
  ocpnBitmap *m_pbm;
#else
  wxBitmap *m_pbm;
#endif

  wxImage *m_pimage;

#ifdef __PIX_CACHE_DIBSECTION__
  wxDIB *m_pDS;
#endif

#ifdef __PIX_CACHE_X11IMAGE__
  XImage *m_pxim;
  Display *xdisplay;
  ocpnXImage *m_pocpnXI;

#endif

#ifdef ocpUSE_MITSHM
  XShmSegmentInfo *pshminfo;
#endif

#ifdef __PIX_CACHE_PIXBUF__
  unsigned char *m_pdata;
  GdkPixbuf *m_pixbuf;
#endif
};

#ifdef ocpnUSE_ocpnBitmap

//-------------------------------------------------------------------------------
//      ocpn_Bitmap Definition
//          with helpers
//-------------------------------------------------------------------------------

#ifdef __WXMSW__
#include <wx/msw/gdiimage.h>
#include <wx/msw/dib.h>
#endif

#ifdef __WXX11__
#include <wx/x11/private.h>
#endif

class WXDLLEXPORT wxDC;
class WXDLLEXPORT wxControl;
class WXDLLEXPORT wxBitmap;
class WXDLLEXPORT wxBitmapHandler;
class WXDLLEXPORT wxIcon;
class WXDLLEXPORT wxMask;
class WXDLLEXPORT wxCursor;
class WXDLLEXPORT wxControl;
class WXDLLEXPORT wxImage;
class WXDLLEXPORT wxPalette;

// ----------------------------------------------------------------------------
// ocpnBitmapo: an optimized wxBitmap
// ----------------------------------------------------------------------------

class /*WXDLLEXPORT*/ ocpnBitmap : public wxBitmap {
public:
  // default ctor creates an invalid bitmap, you must Create() it later
  ocpnBitmap();  //{ Init(); }

  // ctor
  // Create from Data
  ocpnBitmap(unsigned char *pPix, int width, int height, int depth) {
    (void)CreateFromData(pPix, width, height, depth);
  }

  // ctor
  // Create from wxImage
  ocpnBitmap(const wxImage &image, int depth) { CreateFromImage(image, depth); }

#ifdef __WXX11__
  // Create from ocpnXImage
  ocpnBitmap(ocpnXImage *ocpn_Ximage, int width, int height, int depth) {
    CreateFromocpnXImage(ocpn_Ximage, width, height, depth);
  }
#endif

  // Implementation
public:
protected:
  //    creates the bitmap from data, supposed to be called from ctor
  bool CreateFromData(void *pPix, int width, int height, int depth);

  //    or from wximage
  bool CreateFromImage(const wxImage &image, int depth);

//    or from ocpnXimage
#ifdef __WXX11__
  bool CreateFromocpnXImage(ocpnXImage *poXI, int width, int height, int depth);
#endif
};

#endif  // ocpnUSE_ocpnBitmap

//----------------------------------------------------------------------------
//      ocpnMemDC Definition
//----------------------------------------------------------------------------

class /*WXDLLEXPORT*/ ocpnMemDC : public wxMemoryDC {
public:
  ocpnMemDC();

  //      void SelectObject(const wxBitmap&
  //      bitmap){wxMemoryDC::SelectObject(bitmap);}

  //    Satisfy wxX11 2.8.0
  void SelectObject(wxBitmap &bitmap) { wxMemoryDC::SelectObject(bitmap); }

//    Add a method to select a DIB section directly into the DC
#ifdef ocpnUSE_DIBSECTION
  void SelectObject(wxDIB &dib);
#endif

protected:
private:
#ifdef ocpnUSE_DIBSECTION
  wxDIB *m_pselectedDIB;
#endif
};

#endif  // _OCPN_PIXEL_H_
