/***************************************************************************
 *   Copyright (C) 2005 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.             *
 ***************************************************************************/
#ifndef SPECTRUM_H
#define SPECTRUM_H

/**
A class for manipulation and drawing of spectra
 
@author Armando Navarro Vazquez
*/

#include <vector>

#include <QString>
#include <QRect>


#include "fidarray.h"

class QPainter;
class Spectrum
{
struct   zoom
{
  zoom() { firstpoint=0; lastpoint=0; ratio=1.0f; offset=fleft=0.0f; fright=1.0f; }
  int npoints; int firstpoint; int lastpoint; float ratio; float offset;double fleft;double fright;

  void SetPoints(int npoints)
  {
    firstpoint=ceil(npoints*fleft);
    lastpoint=floor(npoints*fright);
    if(lastpoint>(npoints-1))
      lastpoint=npoints-1;
  }

  void SetPoints(int npoints, int left,int right)
  {
    fleft=(float)left/((float)npoints-1);
    fright=(float)right/((float)npoints-1);
    SetPoints(npoints);
  }

  void reset(int size)
  {
    fleft=0.0f;
    fright=1.0f;
    firstpoint=0;
    lastpoint=size-1;
  }

} ;
public:
  Spectrum();
  virtual ~Spectrum();
fidarray& Data() { return m_data; }
  const fidarray& Data() const { return m_data; }
  virtual void Draw(QPainter* p, const QRect& rect);
  void DrawVector(QPainter* p, const QRect& rect);
  virtual void UpdateDrawing(const QRect& rect, bool autoscale=false);
  void SetNucleus(const QString& nucleus) { m_nucleus=nucleus; }
  const QString& Nucleus() const { return m_nucleus; }
  void SetSW(float sw) { m_sw=sw; }
  float SW() const { return m_sw; }
  void SetO1(float o1) { m_O1=o1; }
  float O1() const { return m_O1; }
  void SetOffset(float offset) { m_offset=offset; }
  float Offset() const { return m_offset; }
  void SetBaseLine(float f) { m_baseline=f; }
  float Baseline() const { return m_baseline; }
  void SetScale(float f) { m_scale=f; }
  float Scale() const { return m_scale; }
  virtual void GetLimits(float& left,float& right) =0;
  float GetAQ() const { return m_data.size()/m_sw; }
  void SetZoom(float left,float right);
  virtual void ResetZoom() { m_zoom.reset(m_data.size()); }
  virtual void MoveZoom(float inc);
  virtual QString Info(const QRect& rect, const QPoint& point)  const=0;
  /** Do zero filling to n points, if n=0 (default value) the 
  data will be filled to the closest power of two*/
  void ZeroFilling(size_t n=0);
  /** Phase the spectrum by angle0 in zeroth order*/
  void ZerothOrderPhase(float angle);
  /** Phase the spectrum by angle 1 in first order*/
  void FirstOrderPhase(float angle);
  /**Return the maximum point */ 
  size_t AbsMax(bool real=true,bool zoom=false);
  /** Return the position on the widget holding the spectrum*/
  QPoint PosOnWidget(size_t pos, const QRect& rect) const;
  /**return the point at position point in the widget*/
  size_t PosAt(const QPoint& point,const QRect& rect) const;
  /**return the Y value of the scale at screen point point*/
  float YValue(int yscreen, const QRect& rect) const;
  /** Set the pivot on maximum of spectrum*/
  void SetPivot();
  /** Get the pivot position*/
  size_t Pivot() const { return m_pivotpos; }
  void ScreenLimits(size_t& first,size_t& last) const;
  void SetXUnits(const char* xunits) { m_xunits=QString(xunits); }
  void SetYUnits(const char* yunits) { m_yunits=QString(yunits); }
  QString XUnits() const { return m_xunits; }
  QString YUnits() const { return m_yunits; }
protected:
  zoom m_zoom;  
  fidarray m_data;  
  std::vector<QPoint> m_points;
private:


  QString m_nucleus;
  QString m_xunits;
  QString m_yunits;
  float m_sw;
  float m_O1;
  float m_offset;
  float m_baseline;
  float m_scale;
  size_t m_pivotpos;

};

#endif
