/*

  xmunipack - display's headers

  Copyright © 2012-13, 2018 F.Hroch (hroch@physics.muni.cz)

  This file is part of Munipack.

  Munipack 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 3 of the License, or
  (at your option) any later version.

  Munipack 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 Munipack.  If not, see <http://www.gnu.org/licenses/>.

*/

#include "plot.h"
#include "fits.h"
#include "enum.h"
#include "event.h"
#include "mconfig.h"
#include "types.h"
#include <wx/wx.h>
#include <wx/html/htmlwin.h>
#include <list>
#include <map>

class MuniCanvasMini: public wxWindow
{
public:
  MuniCanvasMini(wxWindow *, int, int);
  wxSize DoGetBestSize() const;
  void SetArray(const FitsArray&);

private:

  int size,scale;
  wxBitmap canvas;
  FitsImage image;
  FitsTone tone;
  FitsItt itt;
  FitsPalette pal;
  FitsColor colour;
  wxPoint crosshair;

  void OnPaint(wxPaintEvent&);
  void OnUpdate(wxUpdateUIEvent&);
  void OnMouseMotion(MuniSlewEvent&);
  void OnFullTune(MuniFullTuneEvent&);
  void Render(const wxPoint&);

};


// OBSOLETE ???????
class MuniDetail: public wxDialog
{
public:
  MuniDetail(wxWindow *, wxWindowID, const wxPoint&, const wxSize&,
	     MuniConfig *);

  void Assign(const FitsCoo&, const FitsValue&);

private:

  MuniConfig *config;
  FitsCoo coords;
  FitsValue values;

  MuniCanvasMini *zoom;
  wxChoice *coochoice, *valchoice;
  wxString values_str,xcoo_str,ycoo_str;

  void OnMouseMotion(MuniSlewEvent&);
  void OnChoiceCoo(wxCommandEvent&);
  void OnChoiceVal(wxCommandEvent&);
  void OnClose(wxCloseEvent&);
  void OnUpdateValue(wxUpdateUIEvent&);
  void OnUpdateXCoo(wxUpdateUIEvent&);
  void OnUpdateYCoo(wxUpdateUIEvent&);
  void OnUpdateXlabel(wxUpdateUIEvent&);
  void OnUpdateYlabel(wxUpdateUIEvent&);

};


class MuniDisplayPanel: public wxScrolledWindow
{
public:
  MuniDisplayPanel(wxWindow *w, MuniConfig *c);

  void SetArray(const FitsArray&);
  void OnFullTune(MuniFullTuneEvent&);

private:

  MuniConfig *config;
  FitsValue value;
  FitsCoo coords;
  FitsArray array;
  bool hist_init, mini_init;
  wxString val_label, xval_str,yval_str,zval_str,
    acoo_str,dcoo_str,xcoo_str,ycoo_str;
  MuniCanvasMini *zoom;
  wxStaticText *xval,*yval,*zval,*xcoo,*ycoo,*acoo,*dcoo,
    *label_alpha, *label_delta, *label_x, *label_y;
  wxFlexGridSizer *xgrid;
  wxButton *valtype,*ctype;
  wxStaticText *value_label;
  MuniPlotHisto *phisto;
  wxHtmlWindow *html;
  std::list<long> ids;
  std::list<wxString> labels;

  void OnIdle(wxIdleEvent&);
  void OnPopVal(wxCommandEvent&);
  void OnPopCoo(wxCommandEvent&);
  void OnCooUnit(wxCommandEvent&);
  void OnValUnit(wxCommandEvent&);
  void OnMouseMotion(MuniSlewEvent&);
  void OnUpdateXValue(wxUpdateUIEvent&);
  void OnUpdateYValue(wxUpdateUIEvent&);
  void OnUpdateZValue(wxUpdateUIEvent&);
  void OnUpdateXCoo(wxUpdateUIEvent&);
  void OnUpdateYCoo(wxUpdateUIEvent&);
  void OnUpdateACoo(wxUpdateUIEvent&);
  void OnUpdateDCoo(wxUpdateUIEvent&);
  void SetValueLabel(int);
  void UpdateCooPanel(int);
};


class DisplayShrinkRender: public wxThread
{
  wxEvtHandler *handler;
  FitsImage image;
  FitsTone tone;
  int shrink;
  int thisid;
  ExitCode Entry();

 public:
  DisplayShrinkRender(wxEvtHandler *, const FitsImage&, const FitsTone&,
		      int, int);
  virtual ~DisplayShrinkRender();
};


class DisplayTuneRender: public wxThread
{
  wxEvtHandler *handler;
  FitsImage image;
  FitsTone tone;
  FitsItt itt;
  FitsPalette pal;
  FitsColor colour;
  int thisid;
  ExitCode Entry();

 public:
  DisplayTuneRender(wxEvtHandler *, const FitsImage&, const FitsTone&,
		    const FitsItt&, const FitsPalette&, const FitsColor&, int);
  virtual ~DisplayTuneRender();
};


class MuniDisplayCanvas: public wxScrolledCanvas
{
public:
  MuniDisplayCanvas(wxWindow *w, MuniConfig *c);
  virtual ~MuniDisplayCanvas();

  void SetHdu(const FitsArray&, const wxImage&);
  void SetInitShrink(int);
  void InvokeRendering();
  void StopRendering();
  FitsTone GetTone() const { return tone; };
  FitsItt GetItt() const { return itt; };
  FitsPalette GetPalette() const { return pal; }
  FitsColor GetColor() const { return color; }
  wxImage GetImage() const;
  wxPoint GetCartesianPosition(const wxPoint&) const;

  void OnTuneFine(MuniTuneEvent&);
  void OnValueType(wxCommandEvent&);
  void OnCooType(wxCommandEvent&);
  void OnAstrometry(MuniAstrometryEvent&);
  void OnPhotometry(MuniPhotometryEvent&);
  void OnDraw(MuniDrawEvent&);
  void AddLayer(const MuniLayer&);
  void RemoveLayers(int);

private:

  friend class DisplayShrinkRender;
  friend class DisplayTuneRender;
  wxCriticalSection renderCS;
  wxThread *render;
  int canvasid;


  wxWindow *topwin;
  MuniConfig *config;
  wxEvtHandler *handler;

  FitsArray array;
  wxImage icon, canvas;
  int xoff,yoff,xdrag0,ydrag0,vbX,vbY;
  FitsImage fitsimage, scaled;
  FitsPalette pal;
  FitsTone tone;
  FitsItt itt;
  FitsColor color;
  int value_type, coo_type;
  int scaleicon;
  int shrink, zoom;
  bool zooming, update_zoom, shrinking, tunning, completed;
  bool dragging,invoking,rendering,finished;
  bool astrometry;
  double xcen, ycen, acen, dcen, ascale, aangle;
  wxPoint crosshair;
  std::list<MuniLayer> layers;

  void OnClose(wxCloseEvent&);
  void OnSize(wxSizeEvent&);
  void OnPaint(wxPaintEvent&);
  void OnMouseMotion(wxMouseEvent&);
  void OnMouseEnter(wxMouseEvent&);
  void OnMouseLeave(wxMouseEvent&);
  void OnMouseWheel(wxMouseEvent&);
  void OnClick(wxMouseEvent&);
  void OnLeftUp(wxMouseEvent&);
  void OnRenderFinish(MuniRenderEvent&);
  void OnSubRender(MuniRenderEvent&);
  void Reset();
  //  void OverlayBitmap(const vector<MuniDrawBase *>&);
  //  void OverlayGrid(const vector<wxGraphicsPath>&);
  void OnClipValue(wxCommandEvent&);
  void OnClipCoo(wxCommandEvent&);
  void OnKeyDown(wxKeyEvent&);
  void OnMenu(wxMouseEvent& event);
  void OnIdle(wxIdleEvent&);
  //  void DrawSVG(wxPaintDC&, const wxXmlDocument&);
  void DrawLayer(wxPaintDC&, const MuniLayer&);
  void ConvertCoo(double,double,double&,double&);

  void InitCanvas();
  void UpdateCanvas(int,int);
  void UpdateCanvas();
  void UpdateTune();
  void UpdateScale(int);
  void UpdateScale();
  void UpdateScroll();
  void StartRendering();

};

class MuniDisplayCaptionInfo: public wxPanel
{
  MuniConfig *config;
  FitsArray array;
  bool init;

  wxStaticText *object, *colour, *exptime, *date, *time,
    *label_object, *label_colour;

  void OnIdle(wxIdleEvent&);

public:
  MuniDisplayCaptionInfo(wxWindow *, MuniConfig *);
  void SetArray(const FitsArray&);

};


class MuniDisplayCaptionColour: public wxPanel
{
  FitsArray array;
  bool cie1931xyz;
  wxStaticText *colours[3];
  bool update;
  double x,y;

  void OnIdle(wxIdleEvent&);
  void OnMouseMotion(MuniSlewEvent&);
  wxString print(float);

public:
  MuniDisplayCaptionColour(wxWindow *, bool);
  void SetArray(const FitsArray&);
  void UnsetArray();

};

class MuniDisplayCaptionMotion: public wxPanel
{
  MuniConfig *config;
  FitsValue value;
  FitsCoo coords;
  FitsArray array;
  wxString cspace;

  wxStaticText *quantity, *label_quantity, *units_quantity,
    *alpha, *delta, *xpix, *ypix;
  wxFlexGridSizer *quantitysizer, *pixsizer, *coosizer;
  wxButton *options;
  MuniDisplayCaptionColour *xyz, *lab;
  std::map<long,wxString> hash;
  bool init, update, hascal, show_wcs;
  int x,y;

  void OnIdle(wxIdleEvent&);
  void OnOptions(wxCommandEvent&);
  void OnPopOptions(wxCommandEvent&);
  void OnMouseMotion(MuniSlewEvent&);

public:
  MuniDisplayCaptionMotion(wxWindow *, MuniConfig *);
  void SetArray(const FitsArray&);

};

class MuniDisplayCaption: public wxPanel
{
  MuniConfig *config;
  wxTimer timer;
  wxRect rect;
  bool inside;

  MuniDisplayCaptionInfo *info;
  MuniDisplayCaptionMotion *motion;

  void OnMouseMotion(MuniSlewEvent&);
  void OnTimer(wxTimerEvent&);

public:
  MuniDisplayCaption(wxWindow *, MuniConfig *);
  void SetArray(const FitsArray&);

};

class MuniMagnifierGlass: public wxWindow
{
  int width, height, scale;
  bool defined;
  wxBitmap canvas;
  wxImage image;
  wxPoint crosshair;

  void OnPaint(wxPaintEvent&);
  void OnSize(wxSizeEvent&);
  void UpdateCanvas(int,int,int,int);
  void UpdateBlur(wxDC&);
  void RandomBlur(wxDC&);
  void OnScale(wxCommandEvent&);
  void OnMouseMotion(MuniSlewEvent&);
  void Clear(wxDC&);

public:
  MuniMagnifierGlass(wxWindow *, const wxSize&, int);
  void SetImage(const wxImage&);
  void UnsetImage();
  int GetScale() const;

};


class MuniDisplayMagnifier: public wxFrame
{
  MuniConfig *config;

  MuniMagnifierGlass *zoom;
  wxSlider *slider;
  void OnMouseMotion(MuniSlewEvent&);
  void OnClose(wxCloseEvent&);
  void OnScale(wxCommandEvent&);

public:
  MuniDisplayMagnifier(wxWindow *, MuniConfig *);
  void SetImage(const wxImage&);
  void UnsetImage();
  int GetScale() const;

};
