/*

  xmunipack - plplot backend

  Copyright © 2010-2014 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 "xmunipack.h"
#include "mathplot.h"
#include "plot.h"
#include <wx/wx.h>
#include <vector>
#include <limits>

using namespace std;


class mpHistogram: public mpLayer
{
  FitsHisto hist;
  int idx;

public:
  mpHistogram(const FitsHisto& h): mpLayer(), hist(h), idx(0) {}
  void Rewind() { idx = 0; } 
  double GetMinX() { return hist.CentsMin(); }
  double GetMaxX() { return hist.CentsMax(); }
  double GetMinY() { return 0; }
  double GetMaxY() { 
    int hmax = 1;
    for(int i = 0; i < hist.NBins(); i++ ) {
      if( hist.Hist(i) > hmax )
        hmax = hist.Hist(i);
    }
    return hmax;
  }
  void Plot(wxDC& dc, mpWindow& win) {

    dc.SetPen(*wxLIGHT_GREY_PEN);

    for(int i = 0; i < hist.NBins(); i++) {
      wxCoord x,y;
      x = win.x2p(hist.Cents(i));
      y = win.y2p(hist.Hist(i));
      dc.DrawLine(x,win.y2p(0),x,y);
    }
  }
};



// -- MuniPlotHisto  --------------------------------------------

MuniPlotHisto::MuniPlotHisto(wxWindow *w, bool t):
  mpWindow(w,wxID_ANY),
  itt_plot(false),axes(t),hmax(1),xmin(0.0),xmax(0.0),
  bestsize(axes ? wxSize(300,185) : wxSize(162,100))
{
}

wxSize MuniPlotHisto::DoGetBestSize() const
{
  return bestsize;
}

void MuniPlotHisto::SetItt(const FitsItt& i) 
{ 
  itt_plot = true;
  itt = i;
  //  itt = i;
  //  Refresh();
}

void MuniPlotHisto::SetHisto(const FitsHisto& hl)
{
  hlist.clear();
  hlist.push_back(hl);
  SetHisto(hlist);
}

void MuniPlotHisto::SetHisto(const std::vector<FitsHisto>& h)
{
  vector<FitsHisto> hs = h;
  //  hlist = h;
  hlist.clear();
  for(vector<FitsHisto>::const_iterator k = hs.begin(); k != hs.end();++k)
    if( k->IsOk() )
      hlist.push_back(*k);

  // search for maximum in histogram
  hmax = 0;
  for(vector<FitsHisto>::const_iterator k = hlist.begin(); k!=hlist.end();++k){
    FitsHisto hist = *k;  
    for(int i = 0; i < hist.NBins(); i++ ) {
      if( hist.Hist(i) > hmax )
        hmax = hist.Hist(i);
    }
  }

  // set range of values
  /*
  FitsHisto hist = hlist[hlist.size() == 1 ? 0 : 1];
  wxASSERT(hist.IsOk());
  xmin = hist.CentsMin();
  xmax = hist.CentsMax();
  */

  xmin = numeric_limits<double>::max();
  xmax = -xmin;
  for(vector<FitsHisto>::const_iterator k = hlist.begin(); k!=hlist.end();++k){
    FitsHisto hist = *k;  
    if( xmin > hist.Cents(0) )
      xmin = hist.Cents(0);
    if( xmax < hist.Cents(hist.NBins()-1) )
      xmax = hist.Cents(hist.NBins()-1);
  }

  /*
  xmin = hist.Cents(0);
  for(int i = 0; i < hist.NBins()-1; i++)
    if( hist.Hist(i) > 0 ) {
      xmin = hist.Cents(i);
      break;
    }

  xmax = hist.Cents(hist.NBins()-1);
  for(int i = hist.NBins()-1; i > 0 ; i--)
    if( hist.Hist(i) > 0 ) {
      xmax = hist.Cents(i);
      break;
    }
  */

  /*
  if( hlist.size() == 1 ) {
    FitsHisto hist = hlist[0];  
    xmin = hist.Cents(0);
    xmax = hist.Cents(hist.NBins()-1);
  }
  else if ( hlist.size() > 1 ) {
    FitsHisto hist = hlist[1];  
    xmin = hist.Cents(0);
    xmax = hist.Cents(hist.NBins()-1);
  }
  */

  //  wxLogDebug("/// %f %f %d",xmin,xmax,hmax); 

  DelAllLayers(true,false);

  if ( ! h.empty() ) {
    mpHistogram *l = new mpHistogram(h[0]);
    wxPen hpen(*wxLIGHT_GREY_PEN);
    hpen.SetWidth(3);
    l->SetPen(hpen);
    AddLayer(l);
  }

  Fit();
}


// --- MuniPlotTable -------------------------------------

/*
MuniPlotTable::MuniPlotTable(const vector<wxRealPoint>& p,const wxColour& c):
  points(p),colour(c)
{
}
*/

// --- MuniPlot ------------------------------------------


// MuniPlot::MuniPlot(wxWindow *w):
//   wxPLplotwindow(w,wxID_ANY,wxDefaultPosition,wxDefaultSize,wxWANTS_CHARS,
// 		 PLPLOT_OPTIONS),
//   xmin(numeric_limits<double>::max()),xmax(numeric_limits<double>::min()),
//   ymin(numeric_limits<double>::max()),ymax(numeric_limits<double>::min())
// {
//   Draw();
// }

// void MuniPlot::AddData(const MuniPlotTable& t)
// {
//   for(size_t i = 0; i < t.points.size(); i++) {
//     wxRealPoint p(t.points[i]);
//     if( p.x < xmin ) xmin = p.x;
//     if( p.x > xmax ) xmax = p.x;
//     if( p.y < ymin ) ymin = p.y;
//     if( p.y > ymax ) ymax = p.y;
//   }

//   tables.push_back(t);
//   Draw();
// }



// void MuniPlot::Draw()
// {
//   wxColour cb = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWFRAME);

//   wxPLplotstream* pls = GetStream();
//   pls->adv( 0 );
//   pls->schr(0.0,3.0);
//   //  pls->scol0a(0,255,255,255,1.0);
//   pls->scol0a(0,cb.Red(),cb.Green(),cb.Blue(),1.0);
//   pls->scol0a(1,0,0,0,1.0);

//   if( tables.empty() ) {
//     pls->vpor(0.01, 0.99, 0.2, 0.99);
//     pls->wind(-0.5, 10.5, 0.0, 1.0);
//     pls->box("bcnt",0.0,0.0,"bct",0.0,0.0);
//   }
//   else {

//     pls->scol0a(2,255,0,0,0.2);
//     pls->scol0a(3,0,255,0,0.2);
//     pls->scol0a(4,0,0,255,0.2);
//     pls->scol0a(5,170,170,170,0.2);

//     pls->scol0a(12,255,0,0,1.0);
//     pls->scol0a(13,0,255,0,1.0);
//     pls->scol0a(14,0,0,255,1.0);
//     pls->scol0a(15,170,170,170,1.0);
    
//     pls->vpor(0.01, 0.99, 0.2, 0.99);
//     pls->wind(xmin, xmax, ymin, ymax);
//     pls->box("bcnt",0.0,0.0,"bct",0.0,0.0);

//   }
//   //    const size_t nh = 50;
// //   PLFLT         hx[nh],hr[nh],hg[nh],hb[nh];
// //     for ( size_t i = 0; i < nh; i++ ) {
// //       double t = (i - 25.0)/10.0;
// //       hx[i] = t;
// //       hr[i] = exp(-(t-1)*(t-1)/2.0);
// //       hg[i] = exp(-(t-0)*(t-0)/2.0);
// //       hb[i] = exp(-(t+1)*(t+1)/2.0);
// //       //      wxLogDebug(_("%f %f"),hx[i],hy[i]);
// //     }


//   RenewPlot();
// }




// Plot Nite

/*
PlotNite::PlotNite(wxWindow *w):
  wxPLplotwindow(w,wxID_ANY,wxDefaultPosition,wxDefaultSize,wxWANTS_CHARS,
		 PLPLOT_OPTIONS),xmin(0.0),xmax(0.0)
{
  Plot();
}

wxSize PlotNite::DoGetBestSize() const
{
  return wxSize(300,185);
}

void PlotNite::SetColor(const FitsColor& c)
{
  color = c;
  Plot();
}

void PlotNite::SetXrange(double x1, double x2)
{
  xmin = x1;
  xmax = x2;
  Plot();
}

void PlotNite::Plot() {

  wxColour cb = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWFRAME);
  wxColour ct = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
  wxColour ht = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNHIGHLIGHT);

  wxPLplotstream* pls = GetStream();
  pls->adv(0);
  pls->schr(0.0,2.0);

  pls->scol0a(0,cb.Red(),cb.Green(),cb.Blue(),1.0);
  pls->scol0a(1,ct.Red(),ct.Green(),ct.Blue(),1.0);

  pls->vpor(0.1, 0.9, 0.2, 0.9);
  pls->wind(0.95*xmin, 1.05*xmax, 0.0, 1.1);
  pls->box("bcnt",0.0,0.0,"bct",0.0,0.0);

  PLFLT p_xmin, p_xmax, p_ymin, p_ymax;
  pls->gvpw (p_xmin, p_xmax, p_ymin, p_ymax);
  int npoints = 20;
  double step = (p_xmax - p_xmin)/npoints;
  PLFLT x[npoints],y[npoints];
  for(int i = 0; i < npoints; i++) {
    double t = p_xmin + i*step;
    x[i] = t;
    y[i] = color.NightProfile(t);
  }
  pls->scol0a(9,ht.Red(),ht.Green(),ht.Blue(),0.5);
  pls->col0(9);
  pls->width(3);
  pls->line(npoints,x,y);

  pls->width(0);
  pls->col0(1);

  RenewPlot();
}
*/

// MuniPlotUV::MuniPlotUV(wxWindow *w):
//   wxPLplotwindow(w,wxID_ANY,wxDefaultPosition,wxDefaultSize,wxWANTS_CHARS,PLPLOT_OPTIONS),
//   nuv(0),u(0),v(0)
// {
//   Draw();
// }

// MuniPlotUV::~MuniPlotUV()
// {
//   delete[] u;
//   delete[] v;  
// }

// wxSize MuniPlotUV::DoGetBestSize() const
// {
//   return wxSize(200,200);
// }


// void MuniPlotUV::Clear()
// {
//   nuv = 0;
//   delete[] u;
//   delete[] v;
//   Draw();
// }

// void MuniPlotUV::DrawTri(const vector<double>& uu, const vector<double>& vv)
// {
//   wxASSERT(uu.size() == vv.size());

//   delete[] u;
//   delete[] v;

//   nuv = uu.size();
//   u = new PLFLT[nuv];
//   v = new PLFLT[nuv];

//   for(int i = 0; i < nuv; i++) {
//     u[i] = uu[i];
//     v[i] = vv[i];
//   }

//   Draw();
// }


// void MuniPlotUV::Draw()
// {
//   wxColour cb = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWFRAME);

//   wxPLplotstream* pls = GetStream();
//   pls->adv(0);

//   pls->scol0a(0,cb.Red(),cb.Green(),cb.Blue(),1.0);
//   pls->scol0a(1,0,0,0,1.0);

//   //  pls->schr(0.0,3.0);

//   //  pls->vpor(0.0, 1.0, 0.0, 1.0);
//   //  pls->wind(0.0, 1.0, 0.0, 1.0);
//   //  pls->box("bcnt",0.1,0.0,"bcnt",0.1,0.0);
//   pls->env(0.0,1.0,0.0,1.0,2.0,0.0);
//   //  pls->lab("u","v","Triangles in uv space");

//   /*
//   const int npoints = 3;
//   PLFLT x[npoints],y[npoints];
//   x[0] = 0.9; y[0] = 0.9;
//   x[1] = 0.1; y[1] = 0.7;
//   x[2] = 0.7; y[2] = 0.1;
//   */
//   if( nuv > 0 ) 
//     pls->line(nuv,u,v); 

//   RenewPlot();
// }
