/***************************************************************************
 *   Copyright (C) 2006 by Armando Navarro Vazquez   *
 *   qoajnv@usc.es   *
 *                                                                         *
 *   This program 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 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program 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 this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include <qpainter.h>
#include "integrator.h"
#include "spectrum.h"

Integral::Integral(Integrator* integrator,size_t from, size_t to) : m_integrator(integrator) , m_from(from), m_to(to)
{
  fidarray& data=m_integrator->GetSpectrum()->Data();
  if (from < 0 ) m_from==0;
  if ( from >= data.size() )
    m_to=data.size()-1;
  CalculateValue();
}

Integral::~ Integral()
{}

void Integral::SetupDrawingPath(const QRect& clientrect)
{
  std::complex<float> sum;
  fidarray& data=m_integrator->GetSpectrum()->Data();

  QPoint point=m_integrator->GetSpectrum()->PosOnWidget(m_from,clientrect);
  QPoint point1=m_integrator->GetSpectrum()->PosOnWidget(m_to,clientrect);
  m_path.clear();
  m_path.reserve(point1.x()-point.x());
  point.setY(clientrect.top()+m_integrator->Baseline()*clientrect.height());
  m_path.push_back(point);
  size_t from=m_from+1;
  point1=point;

  for(size_t i=from;i<=m_to;i++)
  {



    while ( point1.x() == point.x() && i<=m_to)
    {
      point1=m_integrator->GetSpectrum()->PosOnWidget(i,clientrect);
      sum+=data[i++];

    }

    point1.setY(clientrect.top()+clientrect.height()*m_integrator->Baseline()-sum.real()*m_integrator->Scale()*clientrect.height());
    point=point1;
    m_path.push_back(point);


  }
}

/*float Integral::GetOptimumScale()
{
  
}*/

void Integral::CalculateValue()
{
  std::complex<float> sum(0,0);
  fidarray& data=m_integrator->GetSpectrum()->Data();
  for(size_t i=0;i< data.size();i++)
  {
    sum+=data[i];
  }
  m_value=sum;
}

float Integral::Value(bool real /*=true*/)
{
  if( real)
  {
    return m_value.real();
  }
  else
    return m_value.imag();
}


void Integral::Draw(QPainter* p,const QRect& clientrect)
{
  if (m_path.back().x() < clientrect.left() ) return;
  std::vector<QPoint>::const_iterator it;
  p->drawPoints(&m_path[0],m_path.size());
/*  p->moveTo(m_path.front());
  for(it=m_path.begin();it!=m_path.end();++it)
  {
    p->lineTo(*it);

  }*/
  
}
Integrator::Integrator(Spectrum* sp) : m_spectrum(sp)
{
  m_scale=0.01;
  m_baseline=0.6;
}


void Integrator::AddIntegral(const QRect& region, const QRect& clientrect)
{
  size_t firstwpoint, lastwpoint;
  m_spectrum->ScreenLimits(firstwpoint,lastwpoint);
  float l=static_cast<float>(region.left()-clientrect.left())/clientrect.width();
  float r=static_cast<float>(region.right()-clientrect.left())/clientrect.width();
  size_t first=(lastwpoint-firstwpoint)*l+firstwpoint;
  size_t last=(lastwpoint-firstwpoint)*r+firstwpoint;
  m_integrals.push_back(Integral(this,first,last));
  if (m_integrals.size() == 1)
     CalculateScale();

}

#include <iostream>
void Integrator::CalculateScale()
{
  m_scale=0.2/m_integrals.back().Value();

}

void Integrator::UpdateDrawing(const QRect& clientrect)
{
  std::vector<Integral>::iterator it;
  for(it=m_integrals.begin();it!=m_integrals.end();++it)
  {
    it->SetupDrawingPath(clientrect);
  }
}

void Integrator::Draw(QPainter* p,const QRect& clientrect)
{
  std::vector<Integral>::iterator it;
  for(it=m_integrals.begin();it!=m_integrals.end();++it)
  {
     it->Draw(p,clientrect);
  }
}

