/***************************************************************************
**
**  This file is part of QGpCoreTools.
**
**  This library is free software; you can redistribute it and/or
**  modify it under the terms of the GNU Lesser General Public
**  License as published by the Free Software Foundation; either
**  version 2.1 of the License, or (at your option) any later version.
**
**  This file 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 Lesser General Public
**  License for more details.
**
**  You should have received a copy of the GNU Lesser General Public
**  License along with this library; if not, write to the Free Software
**  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
**
**  See http://www.geopsy.org for more information.
**
**  Created: 2009-04-22
**  Copyright: 2009-2019
**    Marc Wathelet
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#include "Version.h"
#include "Trace.h"
#include "CoreApplication.h"
#include "StringSection.h"
#include "MemoryChecker.h"

namespace QGpCoreTools {

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

  Full description of class still missing
*/

Version::Version(int a, int b, int c, const QString& name)
{
  _a=a;
  _b=b;
  _c=c;
  _releaseName=name;
}

Version::Version(const QString& v)
{
  StringSection vs(v);
  bool ok=true;
  const QChar * ptr=nullptr;
  _a=vs.nextField(ptr, ".").toInt(&ok);
  if(!ok) {
    parseError(v);
    _b=0;
    _c=0;
    return;
  }
  _b=vs.nextField(ptr, ".").toInt(&ok);
  if(!ok) {
    parseError(v);
    _c=0;
    return;
  }
  // C not mandatory
  _c=vs.nextField(ptr, "-", false).toInt(&ok);

  StringSection rn=vs.nextField(ptr, " ");
  if(rn.isValid()) {
    _releaseName=rn.toString();
  }
}

void Version::parseError(const QString& v)
{
  App::log(tr("error parsing version '%1'\n").arg(v));
}

void Version::operator=(const Version& v)
{
  _a=v._a;
  _b=v._b;
  _c=v._c;
  _releaseName=v._releaseName;
}

bool Version::operator<(const Version& v) const
{
  if(_a==0 && _b==0 && _c==0) {               // devel release
    if(v._a==0 && v._b==0 && v._c==0) {
      if(_releaseName.isEmpty()) return false;
      if(v._releaseName.isEmpty()) return true;
      return _releaseName<v._releaseName;
    } else {
      return false;                           // devel and stable/testing cannot be compared
                                              // devel is assumed to be more recent
    }
  } else if(v._a==0 && v._b==0 && v._c==0) {  // devel release
    return true;                              // devel and stable/testing cannot be compared
                                              // devel is assumed to be more recent
  } else {
    if(_a<v._a) return true;
    else if(_a>v._a) return false;
    if(_b<v._b) return true;
    else if(_b>v._b) return false;
    if(_c<v._c) return true;
    else if(_c>v._c) return false;
    if(_releaseName.isEmpty()) return false;
    if(v._releaseName.isEmpty()) return true;
    return _releaseName<v._releaseName;
  }
}

bool Version::operator>(const Version& v) const
{
  if(isDevel()) {               // devel release
    if(v.isDevel()) {
      if(_releaseName.isEmpty()) return true;
      if(v._releaseName.isEmpty()) return false;
      return _releaseName>v._releaseName;
    } else {
      return true;                            // devel and stable/testing cannot be compared
                                              // devel is assumed to be more recent
    }
  } else if(v._a==0 && v._b==0 && v._c==0) {  // devel release
    return false;                             // devel and stable/testing cannot be compared
                                              // devel is assumed to be more recent
  } else {
    if(_a<v._a) return false;
    else if(_a>v._a) return true;
    if(_b<v._b) return false;
    else if(_b>v._b) return true;
    if(_c<v._c) return false;
    else if(_c>v._c) return true;
    if(v._releaseName.isEmpty()) return false;
    if(_releaseName.isEmpty()) return true;
    return _releaseName>v._releaseName;
  }
}

bool Version::operator==(const Version& v) const
{
  return _a==v._a && _b==v._b && _c==v._c && _releaseName==v._releaseName;
}

bool Version::compatible(const Version& v) const
{
  return _a==v._a && _b==v._b;
}

QString Version::toString() const
{
  QString s;
  s+=QString::number(_a);
  s+=".";
  s+=  QString::number(_b);
  s+=".";
  s+=  QString::number(_c);
  if(!_releaseName.isEmpty()) {
    s+="-";
    s+=_releaseName;
  }
  return s;
}

} // namespace QGpCoreTools
