/***************************************************************************
**
**  This file is part of ArrayCore.
**
**  ArrayCore 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.
**
**  ArrayCore 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 Foobar.  If not, see <http://www.gnu.org/licenses/>
**
**  See http://www.geopsy.org for more information.
**
**  Created: 2018-11-09
**  Copyright: 2018-2019
**    Marc Wathelet (ISTerre, Grenoble, France)
**
***************************************************************************/

#include "ArraySelection.h"

namespace ArrayCore {

  /*!
    \class ArraySelection ArraySelection.h
    \brief Brief description of class still missing

    Full description of class still missing
  */

  /*!
    Description of constructor still missing
  */
  ArraySelection::ArraySelection(const ArrayStations * array)
  {
    _array=array;
    _parent=nullptr;
    clear();
  }

  ArraySelection::ArraySelection(const ArraySelection * array)
  {
    _array=array->array();
    if(array->_parent) {
      _parent=array->_parent;
    } else {
      _parent=array;
    }
    clear();
  }

  /*!
    Description of destructor still missing
  */
  ArraySelection::~ArraySelection()
  {
    TRACE;
  }

  void ArraySelection::clear()
  {
    TRACE;
    if(_parent) {
      _selected=_parent->_selected;
      _relativePos=_parent->_relativePos;
    } else {
      int n=_array->count();
      _selected.clear();
      for(int i=0; i<n; i++) {
        _selected.append(i);
      }
      setRelativePos();
    }
  }

  void ArraySelection::select(QVector<int> sel)
  {
    TRACE;
    std::sort(sel.begin(), sel.end());
    unique(sel);
    int n=count();
    for(QVector<int>::iterator it=sel.begin(); it!=sel.end(); it++) {
      if(*it<0 || *it>=n) {
        qDebug() << "Error in index in ArraySelection::setSelection()";
        return;
      }
    }
    for(QVector<int>::iterator it=sel.begin(); it!=sel.end(); it++) {
      *it=_selected.at(*it);
    }
    _selected=sel;
    setRelativePos();
  }

  void ArraySelection::setRelativePos()
  {
    TRACE;
    int n=count();
    _relativePos.resize(n);
    for(int i=0; i<n; i++) {
      _relativePos[i]=_array->relativePos(_selected.at(i));
    }
  }

  QString ArraySelection::toString(Coordinates coord, int precision, char format) const
  {
    TRACE;
    QString s;
    int n=count();
    UtmZone utm;
    if(coord==Absolute) {
      bool ok=true;
      utm=_array->utmZone(ok);
    }
    for(int i=0; i<n; i++) {
      const StationSignals& stat=*at(i);
      s+=stat.name();
      s+=" ";
      switch(coord) {
      case Relative:
        s+=_relativePos[i].toString(precision, format);
        break;
      case Absolute:
        if(utm.isValid()) {
          s+=utm.toString();
          s+=" ";
        }
        s+=stat.coordinates().toString(precision, format);
        break;
      }
      s+="\n";
    }
    return s;
  }


  const StationSignals * ArraySelection::at(int index) const
  {
    TRACE;
    return _array->at(_selected.at(index));
  }

  /*!
    Select all stations that are located at a distance from \a src between
    \a minDistance and \a maxDistance.
  */
  void ArraySelection::select(const Point& src, double minDistance, double maxDistance)
  {
    QVector<int> sel;
    // Absolute coordinates are used in the comparison, the relative positions
    for(int i=count()-1; i>=0; i--) {
      double d=src.distanceTo(at(i)->coordinates());
      if(d>=minDistance && d<=maxDistance) {
        sel.append(i);
      }
    }
    select(sel);
  }

} // namespace ArrayCore

