/*

  xmunipack - display's headers

  Copyright © 2012-13 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/>.

*/

#ifndef _MUNI_PLOT_H_
#include "plot.h"
#endif

#ifndef _FITS_H_
#include "fits.h"
#endif

#ifndef _XMUNIPACK_ENUM_H_
#include "enum.h"
#endif

#ifndef _XMUNIPACK_EVENT_H_
#include "event.h"
#endif

#ifndef _XMUNIPACK_CONFIG_H_
#include "mconfig.h"
#endif

#ifndef _XMUNIPACK_TYPES_H_
#include "types.h"
#endif

#include <wx/wx.h>
#include <list>


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

private:

  int size,scale;
  wxBitmap image;

  void OnPaint(wxPaintEvent&);
  void OnUpdate(wxUpdateUIEvent&);
  
};


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 SetHdu(const FitsArray&, const FitsHisto&);
  
private:

  MuniConfig *config;
  FitsValue value;
  FitsCoo coords;
  FitsArray hdu;
  wxString val_str,val_label,fxcoo_str,fycoo_str,xcoo_str,ycoo_str,tobject,
    tdate,ttime,texp,tband,tsize;
  MuniCanvasMini *zoom;
  wxTextCtrl *val,*xcoo,*ycoo,*acoo,*dcoo;
  wxButton *ctype;
  wxStaticText *value_label;
  MuniPlotHisto *phisto;
  std::list<long> ids;
  std::list<wxString> labels;

  void OnPopVal(wxCommandEvent&);
  void OnPopCoo(wxCommandEvent&);
  void OnCooUnit(wxCommandEvent&);
  void OnValUnit(wxCommandEvent&);
  void OnMouseMotion(MuniSlewEvent&);
  void OnUpdateValue(wxUpdateUIEvent&);
  void OnUpdateXCoo(wxUpdateUIEvent&);
  void OnUpdateYCoo(wxUpdateUIEvent&);
  void OnUpdateACoo(wxUpdateUIEvent&);
  void OnUpdateDCoo(wxUpdateUIEvent&);
  void SetValueLabel(int);

  /*
  void OnUpdateObject(wxUpdateUIEvent&);
  void OnUpdateDate(wxUpdateUIEvent&);
  void OnUpdateTime(wxUpdateUIEvent&);
  void OnUpdateExp(wxUpdateUIEvent&);
  void OnUpdateBand(wxUpdateUIEvent&);
  void OnUpdateSize(wxUpdateUIEvent&);
  */
};


class ImageRender: public wxThread
{
public:
  ImageRender(wxEvtHandler *, const FitsImage&, const FitsImage&, 
	      const FitsDisplay&, double, bool, int, int, int, int);
  virtual ~ImageRender();

private:
  
  wxEvtHandler *handler;
  FitsImage fitsimage,fimage;
  FitsDisplay display;
  double zoom;
  bool zooming;
  int x0,y0,width,height;

  ExitCode Entry();
};


class MuniDisplayCanvas: public wxScrolledCanvas
{
public:
  MuniDisplayCanvas(wxWindow *w, MuniConfig *c);
  virtual ~MuniDisplayCanvas();
  
  wxSize DoGetBestSize() const { return wxSize(162,100); }
  void SetHandler(wxEvtHandler *);
  void SetHdu(const FitsArray&, const wxImage&, const FitsArrayStat&);
  void Render();
  void StopRendering();
  bool IsRendering() const { return render; }
  double GetFitZoom() const;
  double GetZoom() const { return zoom; }
  FitsItt GetItt() const { return itt; };
  FitsPalette GetPalette() const { return pal; }
  FitsColor GetColor() const { return color; }
  wxImage GetImage() { return canvas; }
  bool GetFit() const { return fit; }

  void OnTuneFine(MuniTuneEvent&);
  void OnAstrometry(MuniAstrometryEvent&);
  void OnPhotometry(MuniPhotometryEvent&);
  void OnConfigUpdated(wxCommandEvent&);
  //  void AddOverlay(const vector<MuniDrawBase *>& o) { /*drawobj = o;*/ OverlayBitmap(o); Refresh();}
  //  void ShowGrid(const vector<wxGraphicsPath>& ps) { OverlayGrid(ps); Refresh();}
  void AddLayer(const MuniLayer&);
  void RemoveLayers(int);

  // protected:

  wxCriticalSection renderCS;
  ImageRender *render;

private:

  wxWindow *topwin;
  MuniConfig *config;
  wxMemoryDC memdc;
  std::vector<wxBitmap> overlay;
  wxEvtHandler *handler;

  FitsArray hdu;
  wxImage icon, canvas;
  int xoff,yoff,xdrag0,ydrag0,vbX,vbY;
  FitsImage fitsimage, fimage;
  FitsDisplay display;
  FitsBitmap picture;
  FitsPalette pal;
  FitsItt itt, itt_orig;
  FitsColor color;
  double zoom, zoomfit;
  bool zooming;
  bool dragging,rendering;
  bool stick,fit,astrometry;
  double xcen, ycen, acen, dcen, ascale, aangle;
  //  vector<MuniDrawBase *> drawobj;
  //  std::vector<wxXmlDocument> layers;
  std::list<MuniLayer> layers;

  void OnClose(wxCloseEvent&);
  void OnSize(wxSizeEvent&);
  void OnPaint(wxPaintEvent&);
  void OnErase(wxEraseEvent&);
  void OnScroll(wxScrollWinEvent&);
  void OnMouseMotion(wxMouseEvent&);
  void OnMouseWheel(wxMouseEvent&);
  void OnLeftUp(wxMouseEvent&);
  void OnRenderFinish(MuniRenderEvent&);
  void OnSubRender(MuniRenderEvent&);
  void InitDC(int,int,double);
  void Reset();
  //  void OverlayBitmap(const vector<MuniDrawBase *>&);
  //  void OverlayGrid(const vector<wxGraphicsPath>&);
  void SetInitZoom(double =-1.0);
  void OnStick(wxCommandEvent&);
  void OnKeyDown(wxKeyEvent&);
  void OnMenu(wxMouseEvent& WXUNUSED(event));
  void OnIdle(wxIdleEvent&);
  void InitITT(const FitsArray&, const FitsArrayStat&);
  //  void DrawSVG(wxPaintDC&, const wxXmlDocument&);
  void DrawLayer(wxPaintDC&, const MuniLayer&);
  void ConvertCoo(double,double,double&,double&);

};
