/*

  XMunipack


  Copyright © 2009-2015, 2017 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 _XMUNIPACK_H_
#define _XMUNIPACK_H_
#endif

#include "version.h"
#include "config.h"
#include "fits.h"
#include "enum.h"
#include "types.h"
#include "event.h"
#include "mprocess.h"
#include "mconfig.h"
#include "vocatconf.h"

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

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

#ifndef _XMUNIPACK_ICON_H_
#include "icon.h"
#endif

#include <wx/wx.h>
#include <wx/string.h>
#include <wx/arrstr.h>
#include <wx/list.h>
#include <wx/imaglist.h>
#include <wx/listctrl.h>
#include <wx/srchctrl.h>
#include <wx/html/htmlwin.h>
#include <wx/dataview.h>
#include <wx/listimpl.cpp>
#include <wx/propdlg.h>
#include <wx/tglbtn.h>
#include <wx/process.h>
#include <wx/thread.h>
#include <wx/txtstrm.h>
#include <wx/timer.h>
#include <wx/filepicker.h>
#include <wx/spinctrl.h>
#include <wx/minifram.h>
#include <wx/splitter.h>
#include <wx/notebook.h>
#include <wx/toolbook.h>
#include <wx/treectrl.h>
#include <wx/collpane.h>
#include <wx/combo.h>
#include <wx/grid.h>
#include <wx/palette.h>
#include <wx/dirctrl.h>
#include <wx/choicebk.h>
#include <wx/artprov.h>
#include <wx/animate.h>
#include <wx/dnd.h>
#include <wx/xml/xml.h>

#ifdef __WXDEBUG__
#include <wx/debug.h>
#endif

#include <queue>
#include <vector>
#include <list>




class MuniPreferences: public wxPropertySheetDialog
{
public:
  MuniPreferences(wxWindow *, MuniConfig *);

private:

  MuniConfig *config;
  wxChoice *ocs;
  wxSpinCtrl *temper;
  wxTextCtrl *tu,*tv;
  wxString uwhite,vwhite;

  void Init();
  wxPanel *CreateGeneral(wxWindow *);
  wxPanel *CreateKeywords(wxWindow *);
  wxPanel *CreateColors(wxWindow *);

  void OnClose(wxCloseEvent&);
  void OnColorTemper(wxSpinEvent&);
  void OnColorReset(wxCommandEvent&);
  void OnIdle(wxIdleEvent&);

};


class MuniThumbnail
{
public:
  MuniThumbnail(const FitsMeta&);
  MuniThumbnail(const wxString&);
  MuniThumbnail(wxInputStream&);

  void Load(const wxString&);
  void Load(wxInputStream&);
  void Save(const wxString&);
  void Save(wxOutputStream&);
  bool IsOk() const;


  FitsMeta GetMeta() const;
  void SetMeta(const FitsMeta&);

  wxString GetURL() const;

private:

  FitsMeta meta;

  wxString icon;
  wxArrayString icons;

  wxXmlDocument CreateXML(const FitsMeta&,const wxString&);
  FitsMeta ParseXML(const wxXmlDocument&);
  wxString CreateIconame(const wxString&,const wxString& =wxEmptyString);

};

class FitsOpen: public wxThread
{
public:
  FitsOpen(wxEvtHandler *,const wxString&);
  virtual ~FitsOpen();

private:

  wxString filename;
  wxEvtHandler *handler;

  ExitCode Entry();

};



class MuniFileProperties: public wxDialog
{
public:
  MuniFileProperties(wxWindow *w, const FitsMeta& , const MuniConfig *);

private:

  FitsMeta meta;

};

class MuniDirProperties: public wxDialog
{
 public:
  MuniDirProperties(wxWindow*,const MuniConfig*,const std::vector<FitsMeta>&);

};



class MuniConsoleItem
{
public:
  MuniConsoleItem(const wxString& t, int i): text(t),iindex(i) {}
  wxString GetText() const { return text; }
  int GetImageIndex() const { return iindex; }

private:

  wxString text;
  int iindex;

};


class MuniConsole: public wxFrame
{
public:
  MuniConsole(wxWindow *, MuniConfig *);
  virtual ~MuniConsole();
  void AppendOutput(const wxArrayString&);
  void AppendError(const wxArrayString&);
  void AppendOutput(const wxString&);
  void AppendError(const wxString&);

private:

  MuniConfig *config;
  //  wxTextCtrl *output,*error;
  wxListCtrl *list;
  wxMenu *menuView;
  wxToolBar *tsel;
  wxSearchCtrl *search;
  wxFont fixed;
  std::vector<MuniConsoleItem> listitem;

  int logs;
  bool wrap;

  void OnClose(wxCloseEvent&);
  void OnSize(wxSizeEvent&);
  void FileClose(wxCommandEvent&);
  void SaveOutput(wxCommandEvent&);
  void ClearOutput(wxCommandEvent&);
  void SelectOutput(wxCommandEvent&);
  void AppendItems(size_t);
  void SetLogs(int);
  void SetColumnWidth();
  void Search(wxCommandEvent&);
  void SearchFinish(wxCommandEvent&);
  void OnWrap(wxCommandEvent&);

  DECLARE_EVENT_TABLE()
};


class MuniLog: public wxLogWindow
{
public:
  MuniLog(wxWindow *);
  virtual ~MuniLog();

  virtual bool OnFrameClose(wxFrame *);
  bool Visibility();

private:

  wxWindow *topwin;
  bool visible;

};

class MuniAbout
{
public:
  MuniAbout(const wxIcon&);
};


class MuniHelp: public wxFrame
{
public:
  MuniHelp(MuniConfig *);
  virtual ~MuniHelp();

private:

  wxHtmlWindow *web;
  wxString home;
  wxTextCtrl *turl;
  MuniConfig *config;
  wxToolBar *tbar;
  wxMenu *menuGo,*menuView;

  void OnClose(wxCloseEvent&);
  void OnSize(wxSizeEvent&);
  void FileClose(wxCommandEvent& WXUNUSED(event));
  void FileOpen(wxCommandEvent& WXUNUSED(event));
  void GoBack(wxCommandEvent& WXUNUSED(event));
  void GoForward(wxCommandEvent& WXUNUSED(event));
  void GoHome(wxCommandEvent& WXUNUSED(event));
  void ViewStop(wxCommandEvent& WXUNUSED(event));
  void ViewReload(wxCommandEvent& WXUNUSED(event));
  void GoUrl(wxCommandEvent& WXUNUSED(event));
  void GetUrl(wxCommandEvent&);
  void SelUrl(wxCommandEvent&);
  void PrintHref(wxHtmlCellEvent&);
  void ClickedUrl(wxHtmlLinkEvent&);
  void DefaultBrowser(wxCommandEvent& WXUNUSED(event));
  void UpdateControls();
  void HelpAbout(wxCommandEvent& WXUNUSED(event));

  DECLARE_EVENT_TABLE()
};


// class MuniGraph: public wxPanel
// {
// public:
//   MuniGraph(wxWindow *);
//   ~MuniGraph();

//   void SetItt(const FitsItt& i);
//   void SetHisto(const FitsHisto&);
//   void SetHisto(const std::vector<FitsHisto>&);
//   wxSize DoGetBestSize() const;

// private:

//   FitsItt itt;
//   std::vector<FitsHisto> hlist;
//   wxFont sf;
//   const int strip_width, big_tic, small_tic;

//   void OnPaint(wxPaintEvent&);
//   void OnSize(wxSizeEvent&);
//   void Create();

//   DECLARE_EVENT_TABLE()
// };



// class MuniStrip: public wxPanel
// {
// public:
//   MuniStrip(wxWindow *, const wxSize&, const FitsItt&, const FitsPalette&);

//   void SetItt(const FitsItt&);
//   void SetPalette(const FitsPalette&);

// private:

//   FitsItt itt;
//   FitsPalette pal;
//   wxFont sf;
//   const int strip_height, big_tic, small_tic;
//   wxBitmap strip;

//   void OnPaint(wxPaintEvent&);
//   void OnSize(wxSizeEvent&);
//   void OnIdle(wxIdleEvent&);
//   void Create();

//   DECLARE_EVENT_TABLE()
// };


class MuniLUTus: public wxPanel
{
public:
  MuniLUTus(wxWindow *);
  wxSize DoGetBestSize() const;

  void SetPalette(const FitsPalette&);

private:

  FitsPalette pal;

  void OnPaint(wxPaintEvent&);
  void OnSize(wxSizeEvent&);
  void Create();
};


class MuniThumbCanvas: public wxWindow
{
public:
  MuniThumbCanvas(wxWindow *, const wxBitmap&);
  //  virtual ~MuniThumbCanvas() {}
  void SetIcon(const wxBitmap&);
  void SetIcon(const wxImage&);

private:

  wxBitmap icon;

  void OnPaint(wxPaintEvent& WXUNUSED(event));
  void DrawIcon();

  DECLARE_EVENT_TABLE()
};



class MuniBaseDialog: public wxDialog
{
public:
  MuniBaseDialog(wxWindow *,const wxString&,MuniConfig *,const wxString&);
  virtual ~MuniBaseDialog();

protected:

  MuniConfig *config;
  MuniPipe pipe;
  wxTimer timer;
  bool running, readonly;
  int exitcode;
  wxString file,workingfile;

  void OnTimer(wxTimerEvent&);
  void OnFinish(wxProcessEvent&);
  bool RunProcess(MuniProcess *p);


};

class MuniPhotometryLayer
{
public:
  MuniPhotometryLayer(): gold(wxColour(255,215,0,240)),DarkOrange2(wxColour(238,118,0)) {}
  MuniLayer GetLayer() const;
  bool IsEmpty() const { return objects.empty(); }
  void DrawObjects(const std::vector<double>&,const std::vector<double>&,const std::vector<double>&);

private:

  const wxColour gold,DarkOrange2;
  std::vector<wxObject *> objects;

};

class MuniPhotometry: public MuniBaseDialog
{
public:
  MuniPhotometry(wxWindow *,MuniConfig *, const wxString&);
  virtual ~MuniPhotometry();

  wxString GetBackup() const;

private:

  wxGauge *progress;
  wxButton *calbutt;
  double fwhm,thresh,saturation,readnoise,phpadu;
  wxString backupfile;
  bool erase,apply,showtooltip;
  std::list<int> ids;

  bool ParseProcessing(const wxArrayString&);
  void EraseCanvas();
  void OnTimer(wxTimerEvent&);

  void OnUpdateUI(wxUpdateUIEvent&);
  void OnIdle(wxIdleEvent&);
  void OnFwhm(wxSpinDoubleEvent&);
  void OnThresh(wxSpinDoubleEvent&);
  void OnSaturation(wxSpinDoubleEvent&);
  void OnReadNoise(wxSpinDoubleEvent&);
  void OnPhpADU(wxSpinDoubleEvent&);
  void OnApply(wxCommandEvent&);
  void OnCancel(wxCommandEvent&);
  void OnFinish(wxProcessEvent&);
  void OnPhotometry(wxCommandEvent&);

};


class MuniCone: public wxDialog
{
public:
  MuniCone(wxWindow *,MuniConfig *);
  virtual ~MuniCone();
  wxString GetPath() const { return tmpfile; }

private:

  MuniConfig *config;
  VOCatConf catconf;
  wxAnimationCtrl *throbber;
  wxStaticText *status;
  wxButton *search;
  bool running, apply;
  MuniPipe pipe;

  wxSpinCtrlDouble *wradius, *walpha, *wdelta;
  wxString tmpfile;
  std::list<int> ids;

  void OnUpdateUI(wxUpdateUIEvent&);
  void OnOk(wxCommandEvent&);
  void OnCancel(wxCommandEvent&);
  void OnClose(wxCloseEvent&);
  void OnSearch(wxCommandEvent&);
  void OnFinish(wxProcessEvent&);
  //  void OnSave(wxFileDirPickerEvent&);
  void OnService(wxCommandEvent&);
  bool ParseOutput(const wxArrayString&);

};


class MuniSelectSource: public wxDialog
{
public:
  MuniSelectSource(wxWindow *, MuniConfig *, bool =false);
  virtual ~MuniSelectSource();
  wxString GetPath() const;
  wxString GetId() const;
  int GetType() const;
  bool GetRelative() const;
  bool IsTemporary() const;
  wxString GetLabelRA() const;
  wxString GetLabelDec() const;
  wxString GetLabelPMRA() const;
  wxString GetLabelPMDec() const;
  wxString GetLabelMag() const;

private:

  MuniConfig *config;
  int page;
  wxChoice *choice_ra, *choice_dec, *choice_pmra, *choice_pmdec, *choice_mag;
  wxString reffile,catfile,tmpcatfile,idlabel,label_ra,label_dec,
    label_pmra,label_pmdec,label_mag;
  bool xframe, astrorel;

  void OnUpdateUI(wxUpdateUIEvent&);
  void CreateControls();
  void OnCheckRel(wxCommandEvent&);
  void OnRefFile(wxFileDirPickerEvent&);
  void OnCatFile(wxFileDirPickerEvent&);
  void OnCatVO(wxCommandEvent&);
  bool CheckCatalogue(const wxString&, wxArrayString&);
  void OnChoice(wxCommandEvent&);
  void OnBookChange(wxBookCtrlEvent&);
  void EraseTemp();
  void SetLabels(const wxArrayString&);

};


class MuniAstrometryOptions: public wxPanel
{
public:
  MuniAstrometryOptions(wxWindow *,MuniConfig *);
  ~MuniAstrometryOptions();

  int GetMatchType() const;
  int GetMinMatch() const;
  int GetMaxMatch() const;
  double GetSig() const;
  double GetFSig() const;
  bool GetFullMatch() const;
  wxString GetOutputUnits() const;

private:

  MuniConfig *config;

  double sig, fsig;
  int minmatch, maxmatch, matchtype;
  bool full_match;
  wxString output_units;
  std::list<int> ids;

  void OnUpdateUI(wxUpdateUIEvent&);
  void OnSpinSig(wxSpinDoubleEvent&);
  void OnSpinFSig(wxSpinDoubleEvent&);
  void OnSpinMinMatch(wxSpinEvent&);
  void OnSpinMaxMatch(wxSpinEvent&);
  void OnMatchType(wxCommandEvent&);
  void OnFullMatch(wxCommandEvent&);
  void OnChoiceUnits(wxCommandEvent&);

};

class MuniAstrometry: public wxDialog
{
public:
  MuniAstrometry(wxWindow *,MuniConfig *);
  virtual ~MuniAstrometry();
  void SetFile(const wxString&, const FitsArray&);
  void SetDetectedSources(const FitsTable&);
  wxString GetBackup() const;

private:

  MuniConfig *config;
  wxSpinCtrlDouble *wscale, *wangle, *acenter, *dcenter;
  wxButton *sunit, *calbutt, *stopbutt, *savebutt, *rembutt;
  wxGauge *progress;
  wxStaticText *overlayid, *refcatid, *info, *infolabel, *proginfo, *proglabel;
  wxBoxSizer *autosizer;
  wxCheckBox *overlay_check, *reflex_checkbox;
  FitsArray array;
  FitsTable catalogue, stars, coverlay;
  wxTimer timer;
  wxDateTime start;
  MuniPipe pipe;
  MuniAstrometryOptions *astropt;

  int nstars,nhist;
  double maglim, s0, rms;
  double xoff,yoff,alpha, delta, scale, reflex, angle, amin, dmin, fmin;
  wxString proj,label_ra,label_dec,label_mag, label_pmra, label_pmdec;
  bool init_par, init_file, init_ref, running, parsing, unsaved,
    draw_overlay, edited, relative, tmpcat,readonly,showtooltip;
  wxString file,catfile,reffile,backupfile,workingfile;
  int output_index, page;
  std::vector<int> hist;
  std::vector<double> x,y,u,v;
  std::list<int> ids;

  void OnUpdateUI(wxUpdateUIEvent&);
  void OnIdle(wxIdleEvent&);
  void OnStdButton(wxCommandEvent&);
  void OnCalibrate(wxCommandEvent&);
  void OnCalibrateStop(wxCommandEvent&);
  void OnCalibrateFinish(wxProcessEvent&);
  void OnOverlay(wxCommandEvent&);
  void OnReflex(wxCommandEvent&);
  void OnDrawOverlay(wxCommandEvent&);
  void OnReference(wxCommandEvent&);
  void OnTimer(wxTimerEvent&);
  void CreateControls();
  void RunProcessing();
  void DrawOverlay(const FitsTable&);
  void OnPopScaleUnit(wxCommandEvent&);
  void OnScaleUnit(wxCommandEvent&);
  void OnInitRef(wxCommandEvent&);
  void OnSpinDouble(wxSpinDoubleEvent&);
  void OnTextDouble(wxCommandEvent&);
  FitsTable LoadCatalogue(const wxString&);
  void InitByCatalogue(const FitsTable&);
  void ParseProcessing(const wxArrayString&);
  void Reset();
  void OnSaveWCS(wxCommandEvent&);
  void OnSaveWCSFinish(wxProcessEvent&);
  void OnChoiceProj(wxCommandEvent&);
  void RemoveWorkingFile();
  void EraseTemp();
  bool FinishClean(wxCommandEvent&);
  double Scale(double) const;
  double Period(double) const;
  void OnRemove(wxCommandEvent&);
  void OnRemoveFinish(wxProcessEvent&);
  void OnBookChange(wxBookCtrlEvent&);

};

class MuniAstrolog
{
  wxDateTime datetime;

 public:
  MuniAstrolog();
  MuniAstrolog(const wxDateTime&);

  wxString GetSign() const;
};

class MuniAstrometer: public wxDialog
{
public:
  MuniAstrometer(wxWindow *, MuniConfig *, const std::vector<FitsMeta> &);
  virtual ~MuniAstrometer();

private:

  MuniConfig *config;
  const std::vector<FitsMeta> list;
  wxDataViewListCtrl *mtable;
  wxFilePickerCtrl *fpick;
  wxStaticText *refcatid;
  wxBoxSizer *topsizer;
  wxGauge *gstat;
  wxButton *butt, *catbutt;
  wxTimer timer;
  MuniPipe pipe;
  MuniAstrometryOptions *astropt;

  int findex,lastrow;
  wxString proj, reffile,catfile,label_ra,label_dec,label_pmra,label_pmdec,
    label_mag;
  bool running,astrorel,relative,tmpcat;
  std::list<int> ids;

  void OnClose(wxCloseEvent&);
  void OnUpdateUI(wxUpdateUIEvent&);
  void CreateControls();
  void CreateProcess();
  void SetTable();
  void ParseOutput();
  void OnProcess(wxCommandEvent&);
  void OnTimer(wxTimerEvent&);
  void OnFinish(wxProcessEvent&);
  void OnReference(wxCommandEvent&);
  void OnChoiceProj(wxCommandEvent&);
  void EraseTemp();

};


class MuniCalibrate: public wxDialog
{
public:
  MuniCalibrate(wxWindow *,MuniConfig *, const wxString&);
  wxString GetResult() const;

private:

  MuniConfig *config;
  wxAnimationCtrl *throbber;
  double fwhm,thresh, alpha, delta, radius;
  wxString file, output, catalog, projection, coutput;
  MuniPipe pipe;

  void OnFwhm(wxSpinDoubleEvent&);
  void OnThresh(wxSpinDoubleEvent&);
  void OnCatalog(wxCommandEvent&);
  void OnProjection(wxCommandEvent&);
  void OnAlpha(wxCommandEvent&);
  void OnDelta(wxCommandEvent&);
  void OnRadius(wxCommandEvent&);
  void OnApply(wxCommandEvent&);
  void OnCancel(wxCommandEvent&);
  void OnFinish(wxProcessEvent&);

};


class MuniColoring: public wxDialog
{
public:
  MuniColoring(wxWindow *,MuniConfig *);
  bool SetDropMeta(int, int, const std::vector<FitsMeta>&);

private:

  const int iSize;

  MuniConfig *config;
  wxChoice *cspace;
  wxString filename,dirname,colorspace;
  wxArrayString cchoices, opt;
  std::vector<FitsMeta> metalist;
  std::vector<wxString> param_lines;
  wxListView *list;
  wxImageList *icons;
  int index;
  MuniPipe pipe;
  wxAnimationCtrl *throbber;

  void Init();
  void CreateControls();
  void InitList(const wxString&);
  void SetMeta(int, const FitsMeta&, double =0.0, double =-1.0);

  void OnBandfile(wxFileDirPickerEvent&);
  void OnFilename(wxCommandEvent&);
  void OnDirname(wxFileDirPickerEvent&);
  void OnApply(wxCommandEvent&);
  void OnCancel(wxCommandEvent&);
  void OnFinish(wxProcessEvent&);
  void OnColorspace(wxCommandEvent&);
  void OnListSelected(wxListEvent&);
  void OnUpdateBandfile(wxUpdateUIEvent&);
  void OnUpdateOk(wxUpdateUIEvent&);

};


// assumed to by moved to view related (self-contained) header file
class MuniResume: public wxHtmlWindow
{
public:

  MuniResume(wxWindow *, const MuniConfig *, const FitsMeta&);
  void CreatePage(const FitsMeta&);
  virtual ~MuniResume();

private:

  const MuniConfig *config;
  const wxString filename;
  std::list<wxString> files;

  void OnLinkClicked(wxHtmlLinkEvent&);

};


class MuniDisplay: public wxWindow
{
public:
  MuniDisplay(wxWindow *w, MuniConfig *);

  bool SetHdu(const FitsHdu&, const wxImage&);
  //  virtual void SetOverlay(wxInputStream&);
  virtual void SetStars(FitsTable&);
  bool IsRendering() const;
  void StopRendering();
  double GetZoom() const;
  double GetFitZoom() const;
  FitsItt GetItt() const;
  FitsPalette GetPalette() const;
  FitsColor GetColor() const;
  wxImage GetImage();
  bool GetFit() const;
  void ShowPanel(bool);
  void ShowTune(bool =true);
  void ShowGrid(bool =true);
  void ShowSources(bool, const FitsFile&);
  void Photometry(const wxString&);
  void Astrometry(const wxString&,const FitsTable&);
  void Calibrate(const wxString&);

private:

  MuniConfig *config;
  FitsArray array;
  wxImage thumb;
  wxPanel *panel;
  wxWindow *canvas;
  FitsHisto hist;
  wxFrame *tune;
  MuniAstrometry *astrometry;
  //  MuniPhotometry *photometry;

  void OnClose(wxCloseEvent&);
  void OnCloseTune(wxCloseEvent&);
  void OnCloseAstrometry(wxCommandEvent&);
  //  void OnClosePhotometry(wxCloseEvent&);
  void OnLeaveFullscreen(wxCommandEvent&);
  void OnEnterWin(wxMouseEvent&);
  void OnLeaveWin(wxMouseEvent&);

};



class MuniGrid: public wxGrid
{
public:
  MuniGrid(wxWindow *w, MuniConfig *);

  bool SetHdu(const FitsHdu&);

private:

  FitsTable table;
  int rows_filled;

  void OnIdle(wxIdleEvent&);
};


class MuniHead: public wxTextCtrl
{
public:
  MuniHead(wxWindow *w, MuniConfig *);

  bool SetHdu(const FitsHdu&);

private:

  MuniConfig *config;
  FitsHdu head;

};

class MuniHeader: public wxFrame
{
public:
  MuniHeader(wxWindow *w, MuniConfig *);

  void SetHdu(const FitsHdu&);

private:

  MuniConfig *config;
  MuniHead *header;
  FitsHdu head;
  wxMenu *menuFile, *menuEdit;

  void OnClose(wxCloseEvent&);
  void FileClose(wxCommandEvent&);
  void FileExport(wxCommandEvent&);
  void EditCut(wxCommandEvent&);
  void EditCopy(wxCommandEvent&);
  void EditPaste(wxCommandEvent&);
};

class MuniView: public wxFrame
{
public:
  MuniView(wxWindow *,MuniConfig *);
  virtual ~MuniView();
  void LoadFile(const wxString&);
  void SaveFile(const wxString&);
  void LoadMeta(const FitsMeta&);
  void LoadFileBackup(const wxString&, const wxString&);
  bool IsModified() const;


  // private ?
  FitsOpen *loader;
  wxCriticalSection loaderCS;

private:

  MuniConfig *config;
  FitsFile fits;
  FitsMeta meta;
  int hdusel;
  std::vector<long> viewid;
  wxString result;
  wxArrayString backup;

  wxMenu *menuFile,*menuView,*menuWin;
  wxComboCtrl* structtree;
  wxWindow *place;
  bool onreset;
  MuniColoring *coloring;
  wxLogWindow *console;

  void Clear();

  void ReplacePlace(wxWindow *);

  void CreateSplashing();
  void CreateResume();
  void CreateHead();
  void CreateGrid();
  void CreateDisplay();
  void DeleteSplashing();
  void DeleteResume();
  void DeleteHead();
  void DeleteGrid();
  void DeleteDisplay();

  void SetMeta(const FitsMeta&);
  void StopLoading();

  void HduSelect(int);
  //  void EstimHistos(const FitsFile&);
  int EstimHduSel(const FitsMeta&);
  void MenuSelect(int);
  void TreeSelect(int);

  void OnClose(wxCloseEvent& WXUNUSED(event));
  void OnSize(wxSizeEvent& WXUNUSED(event));
  void FileClose(wxCommandEvent& WXUNUSED(event));
  void FileOpen(wxCommandEvent& WXUNUSED(event));
  //  void NewBrowser(wxCommandEvent& WXUNUSED(event));
  void NewView(wxCommandEvent& WXUNUSED(event));
  void OnFullScreen(wxCommandEvent& WXUNUSED(event));
  void OnTune(wxCommandEvent& WXUNUSED(event));
  void OnPhotometry(wxCommandEvent& WXUNUSED(event));
  void OnAstrometry(wxCommandEvent& WXUNUSED(event));
  void OnCalibrate(wxCommandEvent& WXUNUSED(event));
  void OnShowGrid(wxCommandEvent&);
  void OnShowSources(wxCommandEvent&);
  void OnHeader(wxCommandEvent& WXUNUSED(event));
  void HelpGuide(wxCommandEvent& WXUNUSED(event));
  void HelpAbout(wxCommandEvent& WXUNUSED(event));
  //  void HelpBug(wxCommandEvent& WXUNUSED(event));
  void ViewLog(wxCommandEvent&);
  void FileProperties(wxCommandEvent& WXUNUSED(event));
  void OnPreferences(wxCommandEvent& WXUNUSED(event));
  void ShowToolbar(wxCommandEvent&);
  void OnMenuNegative(wxCommandEvent&);
  void OnMenuItt(wxCommandEvent&);
  void OnMenuPal(wxCommandEvent&);
  void OnMenuStructure(wxCommandEvent&);
  void OnSelectFrame(wxCommandEvent&);
  void OnMenuZoom(wxCommandEvent&);
  void OnCycleZoom(wxCommandEvent&);
  void OnCycleItt(wxCommandEvent&);
  void OnCyclePal(wxCommandEvent&);
  void OnDetailPanel(wxCommandEvent&);
  void OnEnterWin(wxMouseEvent&);
  void OnLeaveWin(wxMouseEvent&);
  //  void SaveAsText(wxString);
  void FileSave(wxCommandEvent& WXUNUSED(event));
  void FileExport(wxCommandEvent& WXUNUSED(event));
  void OnLoadFinish(FitsOpenEvent&);
  void SelectPal(const FitsPalette&);
  void SelectItt(const FitsItt&);
  void OnTuneFine(MuniTuneEvent&);

  void Coloring(wxCommandEvent& WXUNUSED(event));
  void OnColoringFinish(wxCommandEvent&);

  /*
  void OnPhotometry(MuniDialogEvent&);
  void OnPhotometryFinish(wxProcessEvent&);
  */

  void LoadStart(const wxString&);
  //  void OnFileLoad(wxCommandEvent&);
  void OnUpdateFit(wxUpdateUIEvent&);
  void OnUpdateNFit(wxUpdateUIEvent&);
  void OnUpdateInfos(wxUpdateUIEvent&);

  void OnConfigUpdated(wxCommandEvent&);
  void OnResumeHdu(MuniHduEvent&);
  int Unsaved(const wxString&);
  void RemoveBackup();

};

class MuniAnim
{
  // ve stylu totemu nebo vlc pod mac: dole ovladaci prvky,
  // info o obrazku (text) do statusbaru

};




class MuniArchive: public wxEvtHandler
{
public:
  MuniArchive(wxEvtHandler *, const wxString&);

  bool IsReadOnly() const;

  void ChangeDir(const wxString&);
  void MakeDir(const wxString&);
  void DeleteDir(const wxString&);
  void RenameDir(const wxString&,const wxString&);
  wxArrayString GetDirs(const wxString& =wxEmptyString) const;
  wxArrayString GetFiles(const wxString& =wxEmptyString) const;
  wxString GetRoot() const;
  wxString GetAbsPath() const;

  void LoadMeta();
  void StopLoadMeta();
  void FlushMeta(const std::vector<FitsMeta>&, const std::vector<FitsMeta>&);
  std::vector<FitsMeta> GetMeta() const;
  void AppendMeta(const FitsMeta&, long);
  void AppendMeta(const FitsMeta&);
  void AppendMeta(const std::vector<FitsMeta>&);
  void DeleteMeta(const FitsMeta&);
  void DeleteMeta(const std::vector<FitsMeta>&);

  void SetEventHandler(wxEvtHandler *);

  wxThread *loader;
  wxCriticalSection loaderCS;

private:

  wxString GetFullPath(const wxString& =wxEmptyString) const;
  wxString DissolveRoot(const wxString&) const;
  long NextAvailableIndex() const;
  wxArrayString GetItems(const wxString&, int,
			 const wxString& =wxEmptyString) const;
  bool IsAbsPath(const wxString&) const;
  void OnMetaOpen(MetaOpenEvent&);
  void OnMetaFinish(MetaOpenEvent&);

  const wxString root;
  wxString cpath;
  const wxString sep;

  wxEvtHandler *handler;
};



class MuniCollector: public wxTreeCtrl
{
public:
  MuniCollector(wxWindow *);
  void SetArchive(MuniArchive *);
  void SelectLastItem();
  bool IsOk() const;

private:

  wxEvtHandler *handevt;
  MuniArchive *archive;
  wxTreeItemId workplace, current, last, arch;
  wxString origlabel, tmpdir;

  void CreateTree(const wxTreeItemId&);
  virtual void OnSelChanged(wxTreeEvent&);
  virtual void OnItemMenu(wxTreeEvent&);
  virtual void OnEditBegin(wxTreeEvent&);
  virtual void OnEditEnd(wxTreeEvent&);
  virtual void OnEdit(wxCommandEvent&);
  virtual void OnNewArchive(wxCommandEvent&);
  virtual void OnExcludeArchive(wxCommandEvent&);

  DECLARE_EVENT_TABLE()
};


class MetaRender: public wxThread
{
public:
  MetaRender(wxEvtHandler *, MuniConfig*);
  virtual ~MetaRender();

protected:

  wxEvtHandler *handler;
  MuniConfig *config;

  ExitCode Entry();
};

class MuniListCtrl: public wxListCtrl
{
public:
  MuniListCtrl(wxWindow *, long = 0, MuniConfig * = 0);
  virtual ~MuniListCtrl();

  virtual void AddFits(const wxArrayString&);
  virtual void AddMeta(const FitsMeta&);
  virtual void AddMeta(const std::vector<FitsMeta>&);
  virtual void SetMeta(const std::vector<FitsMeta>&);
  virtual void SelectAll();
  virtual void DeSelectAll();
  virtual std::vector<FitsMeta> GetAllMeta() const;
  virtual std::vector<FitsMeta> GetSelectedMeta() const;
  virtual std::vector<FitsMeta> GetAddedMeta() const;
  virtual std::vector<FitsMeta> GetDeletedMeta() const;
  virtual void DeleteMeta(const std::vector<FitsMeta>&);
  virtual bool DeleteAllMeta();
  virtual void Update();

  virtual void PasteMeta(const FitsMeta&);
  virtual void PasteMeta(const std::vector<FitsMeta>&);

  std::vector<FitsMeta> GetClipboard() const;
  void SetClipboard(const std::vector<FitsMeta>&);

  std::vector<unsigned int> GetSelectedIndex() const;
  void SelectItemLast();
  void SelectItem(long);
  void SelectItemRelative(long);

  virtual void Cut();
  virtual void Copy();
  virtual void Paste();
  virtual void Label(int);
  virtual void Sort(int);
  virtual void Reverse(bool);

  void AddItem(const FitsMeta&);

  MetaRender *metarender;
  wxCriticalSection metarenderCS;

protected:

  MuniConfig *config;
  wxImageList *thumbs;
  std::vector<FitsMeta> flist,addlist,dellist;
  std::queue<FitsMeta> metas;

  void OnRightClick(wxListEvent&);
  void OnView(wxCommandEvent& WXUNUSED(event));
  void OnProperties(wxCommandEvent& WXUNUSED(event));
  void OnLabel(wxCommandEvent&);
  void OnSort(wxCommandEvent&);
  void OnReverse(wxCommandEvent&);
  void Sorter();
  void OnMouse(wxMouseEvent&);
  void OnCut(wxCommandEvent&);
  void OnCopy(wxCommandEvent&);
  void OnPaste(wxCommandEvent&);
  void OnSelall(wxCommandEvent&);
  void OnFitsOpen(FitsOpenEvent&);
  void OnMetaLoad(MetaOpenEvent&);
  void OnMetaLoadFinish(MetaOpenEvent&);
  void OnMetaOpenFinish(wxCommandEvent&);
  void StopMetaRender();
  void OnMetaRenderFinish(wxThreadEvent&);

};

class MuniListIcon: public MuniListCtrl
{
public:

  MuniListIcon(wxWindow *, MuniConfig * =0);
  virtual void Update();

private:

  long hitem;
  wxImage himage;

  wxString LabelFits(const FitsMeta&, int);
  virtual void HightLightItem(long,bool);
  int iSize() const;
  double iRatio() const;

  void OnMouse(wxMouseEvent&);
  void OnIdle(wxIdleEvent&);

};

class MuniListList: public MuniListCtrl
{
public:
  MuniListList(wxWindow *, MuniConfig * =0);
  virtual void Update();

private:

  void OnIdle(wxIdleEvent&);

};





class MuniDataObjectMeta: public wxDataObjectSimple
{
public:
  MuniDataObjectMeta();
  MuniDataObjectMeta(const std::vector<FitsMeta>& mlist);
  virtual ~MuniDataObjectMeta();

  size_t GetDataSize() const;
  bool GetDataHere(void *) const;
  bool SetData(size_t, const void *);
  std::vector<FitsMeta> GetMetafitses() const;

private:

  size_t len;
  char *data;
};


class MuniListWindow: public wxWindow
{
public:
  MuniListWindow(wxWindow *, wxWindowID, long = 0, MuniConfig * = 0);

  void AddWindow(wxWindow *);
  void SetStyle(long);

  virtual void AddFits(const wxArrayString&);
  virtual void AddMeta(const FitsMeta&);
  virtual void AddMeta(const std::vector<FitsMeta>&);
  virtual void SetMeta(const std::vector<FitsMeta>&);
  virtual void SelectAll();
  virtual void DeSelectAll();
  virtual std::vector<FitsMeta> GetAllMeta() const;
  virtual std::vector<FitsMeta> GetSelectedMeta() const;
  virtual std::vector<FitsMeta> GetAddedMeta() const;
  virtual std::vector<FitsMeta> GetDeletedMeta() const;
  virtual void DeleteMeta(const std::vector<FitsMeta>&);
  virtual bool DeleteAllMeta();
  virtual void Update();

  std::vector<FitsMeta> GetClipboard() const;
  void SetClipboard(const std::vector<FitsMeta>&);

  std::vector<unsigned int> GetSelectedIndex() const;
  void SelectItemLast();
  void SelectItem(long);
  void SelectItemRelative(long);

  virtual int GetSelectedItemCount() const;
  virtual int GetItemCount() const;

  virtual void Cut();
  virtual void Copy();
  virtual void Paste();
  virtual void Label(int);
  virtual void Sort(int);
  virtual void Reverse(bool);

private:

  MuniConfig *config;
  wxBoxSizer *topsizer;
  MuniListCtrl *list;

  void OnProcess(wxProcessEvent&);
  void OnMetaOpen(FitsOpenEvent&);
  void OnMetaLoad(MetaOpenEvent&);

};

class MuniAverage: public MuniListWindow
{
public:
  MuniAverage(wxWindow *,wxWindowID, long =0, MuniConfig * = 0);

private:

  MuniConfig *config;
  MuniPipe pipe;
  wxTimer timer;

  wxTextCtrl *flabel;
  wxDirPickerCtrl *dirpic;
  wxRadioButton *btype[3];
  wxGauge *gauge;
  wxStaticText *label;

  wxString dirname,bitpix,level,filename[3];
  bool robust;
  int xtype;

  void OnDirname(wxFileDirPickerEvent&);
  void OnOptions(wxCommandEvent&);
  void OnCreate(wxCommandEvent&);
  void OnFlabel(wxCommandEvent&);
  void OnBtype(wxCommandEvent&);
  void OnUpdateButt(wxUpdateUIEvent&);
  void OnFinish(wxProcessEvent&);
  void OnUpdate(wxTimerEvent&);

};

class MuniDarkbat: public MuniListWindow
{
public:
  MuniDarkbat(wxWindow *,wxWindowID, long =0, MuniConfig * = 0);

private:

  MuniConfig *config;
  wxFilePickerCtrl *fpic,*dpic,*bpic;
  wxDirPickerCtrl *dirpic;
  wxRadioButton *r0, *r1, *r2;
  wxButton *bcre;
  wxGauge *gauge;
  wxStaticText *label;
  wxString ffilename,dfilename,bfilename,dirname,bitpix,suffix;
  wxArrayString results;
  int mode;
  MuniPipe pipe;
  wxTimer timer;

  void OnFlatname(wxFileDirPickerEvent&);
  void OnDarkname(wxFileDirPickerEvent&);
  void OnBiasname(wxFileDirPickerEvent&);
  void OnDirname(wxFileDirPickerEvent&);
  void OnResult(wxCommandEvent&);
  void OnOptions(wxCommandEvent&);
  void OnCreate(wxCommandEvent&);
  void OnUpdateDirpic(wxUpdateUIEvent&);
  void OnUpdateButt(wxUpdateUIEvent&);
  void OnClearBias(wxCommandEvent&);
  void OnClearDark(wxCommandEvent&);
  void OnClearFlat(wxCommandEvent&);
  wxString CreateResult(const wxString&) const;
  void OnFinish(wxProcessEvent&);
  void OnUpdate(wxTimerEvent&);

};





class MuniImportRawOptions: public wxDialog
{
public:
  MuniImportRawOptions(wxWindow *, MuniConfig *);

  wxString GetType() const;
  wxString GetBand() const;
  wxString GetBitpix() const;
  wxString GetOverWrite() const;
  wxString GetInterpol() const;
  wxString GetDarkframe() const;
  wxString GetDcoptions() const;
  wxString GetDirs() const;

private:

  MuniConfig *config;
  wxChoice *filters,*interpols;
  wxCheckBox *overs;
  wxRadioButton *type0, *type1, *bitpix0, *bitpix1;
  wxFilePickerCtrl *darks;
  wxDirPickerCtrl *dirs;
  wxTextCtrl *dcopts;

  bool over,type_colour,type_grey,bitpix_16bit,bitpix_float;
  int filter,interpol;
  wxString dark,dcopt,dir;
  wxArrayString fchoices,fopt,ichoices,iopt;

  void Init();
  void CreateControls();
  void OnUpdateUI(wxUpdateUIEvent&);
  void OnDarks(wxFileDirPickerEvent&);
  void OnDirs(wxFileDirPickerEvent&);

};


class MuniBrowserSearch: public wxSearchCtrl
{
public:
  MuniBrowserSearch(wxWindow *, wxWindowID, const wxString& =wxEmptyString,
		    const wxPoint& =wxDefaultPosition,
		    const wxSize& =wxDefaultSize, long =0);

  std::vector<long> Find(const std::vector<FitsMeta>&) const;

private:

  int type;
  wxString muster;

  std::vector<long> FindByName(const std::vector<FitsMeta>&) const;
  std::vector<long> FindByKey(const std::vector<FitsMeta>&) const;
  std::vector<long> FindByAdv(const std::vector<FitsMeta>&) const;

  void OnSearchEnter(wxCommandEvent&);
  void OnSearchButton(wxCommandEvent&);
  void OnSearchFinish(wxCommandEvent&);
  void OnSearchMenu(wxCommandEvent&);
  void OnSearchUpdate(wxCommandEvent&);
  void OnUpdateUI(wxUpdateUIEvent&);

};

class MuniImportRaw: public wxDialog
{
private:

  int fcount;
  wxStaticText *label;
  wxGauge *gauge;
  MuniPipe pipe;
  wxString dcdark;

  void OnFinish(wxProcessEvent&);
  void OnClose(wxCloseEvent&);
  void OnCancel(wxCommandEvent&);
  void CreateControls();
  void CreatePipe(const MuniImportRawOptions&, const wxArrayString&);

public:

  MuniImportRaw(wxWindow *, const MuniImportRawOptions&, const wxArrayString&);
  virtual ~MuniImportRaw();

  void Update(int);
  void LoadFile(const wxString&);

};


class MuniBrowser: public wxFrame
{
public:
  MuniBrowser(wxWindow *, MuniConfig *);
  virtual ~MuniBrowser();

  void FileLoad(const wxString&);
  void FilesLoad(const wxArrayString&);

private:

  MuniConfig *config;
  MuniArchive *archive;
  //  MuniConsole *console;
  wxLogWindow *console;
  wxMenu *menuFile, *menuView, *menuAct, *menuArrange, *menuLabels, *menuHelp;
  MuniListWindow *list;
  MuniView *view;
  wxSplitterWindow *splitter;
  MuniCollector *collector;
  wxToolBar *tbar,*tbot;
  wxToolBarToolBase *tstop,*twarn;
  wxBoxSizer *topsizer;
  wxStaticText *archiveprop;
  wxArrayString errmsg;

  wxStaticText *padding;
  MuniBrowserSearch *search;
  bool metaload;

  void OnClose(wxCloseEvent&);
  void OnSize(wxSizeEvent&);
  void OnIdle(wxIdleEvent&);
  void FileOpen(wxCommandEvent& WXUNUSED(event));
  void FileSave(wxCommandEvent& WXUNUSED(event));
  void OnPreferences(wxCommandEvent& WXUNUSED(event));
  void OnProperties(wxCommandEvent& WXUNUSED(event));
  void FileClose(wxCommandEvent&);
  void OnSall(wxCommandEvent& WXUNUSED(event));
  void OnCut(wxCommandEvent&);
  void OnCopy(wxCommandEvent&);
  void OnPaste(wxCommandEvent&);
  void SelectItem(wxCommandEvent&);
  void OnIconList(wxCommandEvent&);
  void OnZoomMax(wxCommandEvent&);
  void OnZoom(wxCommandEvent&);
  void NewBrowser(wxCommandEvent& WXUNUSED(event));
  void NewView(wxCommandEvent& WXUNUSED(event));
  void OnView(wxCommandEvent& WXUNUSED(event));
  void ViewLog(wxCommandEvent&);
  void ShowLog(wxCommandEvent&);
  void OnActivated(wxListEvent&);
  void OnShowToolbar(wxCommandEvent&);
  void OnShowCollector(wxCommandEvent&);
  void FindStars(wxCommandEvent& WXUNUSED(event));
  void AperturePhot(wxCommandEvent& WXUNUSED(event));
  void ProfilePhot(wxCommandEvent& WXUNUSED(event));
  void Matching(wxCommandEvent& WXUNUSED(event));
  void Astrometry(wxCommandEvent& WXUNUSED(event));
  void Stacking(wxCommandEvent& WXUNUSED(event));
  void Deconvolution(wxCommandEvent& WXUNUSED(event));
  void OnAverage(wxCommandEvent& WXUNUSED(event));
  void OnDarkbat(wxCommandEvent& WXUNUSED(event));
  void OnList(wxCommandEvent&);
  void HelpHelp(wxCommandEvent& WXUNUSED(event));
  void HelpAbout(wxCommandEvent& WXUNUSED(event));
  //  void HelpBug(wxCommandEvent& WXUNUSED(event));
  void OnNewArchive(wxCommandEvent&);
  void OnExcludeArchive(wxCommandEvent&);
  void OnSelChanged(wxTreeEvent&);
  void OnMetaLoad(MetaOpenEvent&);
  void SetArchiveSize();
  void OnLabel(wxCommandEvent&);
  void OnSort(wxCommandEvent&);
  void OnReverse(wxCommandEvent&);
  void OnCancelAction(wxCommandEvent&);
  void ShowInspect(bool);
  void OnConfigUpdated(wxCommandEvent&);

  void OnSearch(wxCommandEvent&);
  void OnSearchFinish(wxCommandEvent&);

  //  void ImportRaw(const MuniImportRawOptions&,const wxArrayString&);

  void SwitchList(int);
  void LoadMeta();

  void OnUpdateArchive(wxUpdateUIEvent&);
  void OnUpdateActmenu(wxUpdateUIEvent&);
  void OnUpdateFilemenu(wxUpdateUIEvent&);
  void OnUpdateTbot(wxUpdateUIEvent&);
  void OnUpdateCut(wxUpdateUIEvent&);
  void OnUpdatePaste(wxUpdateUIEvent&);

};


class XMunipack: public wxApp
{
  bool OnInit();
  int OnExit();
  void OnFatalException();

  MuniConfig *config;

};
