/**********************************************************************************************
   Copyright (C) 2015 Ivo Kronenberg <>

   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 3 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, see <http://www.gnu.org/licenses/>.

**********************************************************************************************/

#include "gis/fit/decoder/CFitDefinitionMessage.h"

#include "gis/fit/defs/CFitProfile.h"
#include "gis/fit/defs/CFitProfileLookup.h"
#include "gis/fit/defs/fit_const.h"

static const quint8 fitArchitecureEndianMask = 0x01;

CFitDefinitionMessage::CFitDefinitionMessage() : CFitDefinitionMessage(fitLocalMesgNrInvalid, false) {}

CFitDefinitionMessage::CFitDefinitionMessage(const CFitDefinitionMessage& copy)
    : globalMesgNr(copy.globalMesgNr),
      architecture(copy.architecture),
      nrOfFields(copy.nrOfFields),
      nrOfDevFields(copy.nrOfDevFields),
      localMesgNr(copy.localMesgNr),
      devFlag(copy.devFlag),
      fields(copy.fields),
      devFields(copy.devFields),
      messageProfile(CFitProfileLookup::getProfile(globalMesgNr)) {
  for (CFitFieldDefinition& field : fields) {
    field.setParent(this);
  }
}

CFitDefinitionMessage::CFitDefinitionMessage(quint8 localMesgNr, bool devFlag)
    : globalMesgNr(fitGlobalMesgNrInvalid),
      architecture(0),
      nrOfFields(0),
      nrOfDevFields(0),
      localMesgNr(localMesgNr),
      devFlag(devFlag),
      fields(),
      devFields(),
      messageProfile(CFitProfileLookup::getProfile(fitGlobalMesgNrInvalid)) {}

void CFitDefinitionMessage::setArchiteture(quint8 arch) { architecture = arch; }

void CFitDefinitionMessage::setGlobalMesgNr(quint16 globalMesgNr) {
  this->globalMesgNr = globalMesgNr;
  messageProfile = CFitProfileLookup::getProfile(globalMesgNr);
}

void CFitDefinitionMessage::setNrOfFields(quint8 nrOfFields) { this->nrOfFields = nrOfFields; }

void CFitDefinitionMessage::setNrOfDevFields(quint8 nrOfDevFields) { this->nrOfDevFields = nrOfDevFields; }

quint8 CFitDefinitionMessage::getArchitectureBit() const { return architecture & fitArchitecureEndianMask; }

void CFitDefinitionMessage::addField(CFitFieldDefinition fieldDef) { fields.append(fieldDef); }

void CFitDefinitionMessage::addDevField(CFitFieldDefinition fieldDef) { devFields.append(fieldDef); }

bool CFitDefinitionMessage::hasField(const quint8 fieldNum) const {
  for (int i = 0; i < fields.size(); i++) {
    if (fieldNum == fields[i].getDefNr()) {
      return true;
    }
  }
  return false;
}

const CFitFieldDefinition& CFitDefinitionMessage::getField(const quint8 fieldNum) const {
  for (int i = 0; i < fields.size(); i++) {
    if (fieldNum == fields[i].getDefNr()) {
      return fields[i];
    }
  }
  // dummy field for unknown field nr.
  static const CFitFieldDefinition dummyDefinitionField;

  return dummyDefinitionField;
}

const CFitFieldDefinition& CFitDefinitionMessage::getFieldByIndex(const quint16 index) const {
  if (index < fields.size()) {
    return fields[index];
  }
  // dummy field for unknown field nr.
  static const CFitFieldDefinition dummyDefinitionField;

  return dummyDefinitionField;
}

const CFitFieldDefinition& CFitDefinitionMessage::getDevFieldByIndex(const quint16 index) const {
  if (index < devFields.size()) {
    return devFields[index];
  }
  // dummy field for unknown field nr.
  static const CFitFieldDefinition dummyDefinitionDevField;

  return dummyDefinitionDevField;
}

QStringList CFitDefinitionMessage::messageInfo() const {
  QStringList list;
  list << QString("Definition %1 (%2) local nr %3, arch %4, # fields %5, # dev fields %6")
              .arg(profile().getName())
              .arg(getGlobalMesgNr())
              .arg(getLocalMesgNr())
              .arg(getArchitectureBit())
              .arg(getNrOfFields())
              .arg(getNrOfDevFields());

  for (const CFitFieldDefinition& field : fields) {
    list << field.fieldInfo();
  }

  for (const CFitFieldDefinition& devField : devFields) {
    list << devField.fieldInfo();
  }

  return list;
}
