/*

  xmunipack - plplot backend

  Copyright © 2010-2014, 2018-9 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)
  {
    wxPen hpen(*wxLIGHT_GREY_PEN);

    // width of bins
    wxSize size(dc.GetSize());
    hpen.SetWidth(size.GetWidth()/hist.NBins()+1);
    dc.SetPen(hpen);

    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);
    }

    // draw decorations
    int width = size.GetWidth();
    int height = size.GetHeight();
    dc.SetBrush(*wxTRANSPARENT_BRUSH);
    dc.SetPen(*wxBLACK_PEN);
    dc.DrawRectangle(0,0,width,height);
    dc.SetPen(*wxWHITE_PEN);
    dc.DrawRectangle(1,1,width-2,height-2);
  }

};


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

MuniPlotHisto::MuniPlotHisto(wxWindow *w):
  mpWindow(w,wxID_ANY), hmax(1),xmin(0.0),xmax(0.0)
{
}

wxSize MuniPlotHisto::DoGetBestSize() const
{
  return wxSize(162,100);
}

void MuniPlotHisto::SetArray(const FitsArray& a)
{
  wxASSERT(a.IsOk());
  hlist.clear();
  hlist.push_back(FitsHisto(a));
  Plot();
}

void MuniPlotHisto::SetArray(const std::vector<FitsArray>& arrays)
{
  hlist.clear();
  for(vector<FitsArray>::const_iterator a = arrays.begin(); a!=arrays.end();++a)
    if( a->IsOk() ) {
      hlist.push_back(FitsHisto(*a));
    }

  Plot();
}

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

  // set range of values
  xmin = numeric_limits<double>::max();
  xmax = -xmin;
  for(vector<FitsHisto>::const_iterator h = hlist.begin(); h!=hlist.end();++h){
    FitsHisto hist(*h);
    if( xmin > hist.CentsMin() )
      xmin = hist.CentsMin();
    if( xmax < hist.CentsMax() )
      xmax = hist.CentsMax();
  }
  //wxLogDebug("/// %f %f %d",xmin,xmax,hmax);

  DelAllLayers(true,false);

  if ( ! hlist.empty() ) {
    mpHistogram *l = new mpHistogram(hlist[0]);
    /*
    vector<double> x,y;
    FitsHisto h = hlist[0];
    for(size_t i = 0; i < h.NBins(); i++) {
      x.push_back(h.Cents(i));
      y.push_back(h.Hist(i));
    }
    mpFXYVector *l = new mpFXYVector("");
    l->SetData(x,y);
    */
    wxPen hpen(*wxLIGHT_GREY_PEN);
    hpen.SetWidth(10);
    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();
// }
