/**********************************************************************************************
   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/CFitHeaderState.h"

/**
 * byte
 * 0: the header size without crc (12 for the current version)
 * 1: protocol version
 * 2: profil version LSB
 * 3: profil version MSB
 * 4: data size LSB
 * 5: data size
 * 6: data size
 * 7: data size
 * 8: "."
 * 9: "F"
 * 10: "I"
 * 11: "T"
 * 12: CRC LSB
 * 13: CRC MSB
 */

static const quint8 fitProtocolVersionMajor = 2;
static const quint8 fitProtocolMajorVersionShift = 4;
static const quint8 fitProtocolMajorVersionMask = 0x0F << fitProtocolMajorVersionShift;

void CFitHeaderState::reset() {
  setFileLength(3);  // Header byte + CRC.
  offset = 0;

  setTimestamp(0);
  resetFileBytesRead();
}

decode_state_e CFitHeaderState::process(quint8& dataByte) {
  bool invalid = false;
  switch (offset++) {
    case 0:
      // header length
      headerLength = dataByte;
      setFileLength(headerLength + 2);
      break;

    case 1:
      // protocol version
      if ((dataByte & fitProtocolMajorVersionMask) > (fitProtocolVersionMajor << fitProtocolMajorVersionShift)) {
        throw tr("FIT decoding error: protocol %1 version not supported.").arg(dataByte & fitProtocolMajorVersionMask);
      }
      break;

    case 4:
      // data size
      dataSize = (quint32)(dataByte & 0xFF);
      break;

    case 5:
      // data size
      dataSize |= (quint32)(dataByte & 0xFF) << 8;
      break;

    case 6:
      // data size
      dataSize |= (quint32)(dataByte & 0xFF) << 16;
      break;

    case 7:
      // data size
      dataSize |= (quint32)(dataByte & 0xFF) << 24;
      setFileLength(dataSize + headerLength + 2);  // include crc
      break;

    case 8:
      // "."
      invalid = (dataByte != '.');
      break;

    case 9:
      // "F"
      invalid = (dataByte != 'F');
      break;

    case 10:
      // "I"
      invalid = (dataByte != 'I');
      break;

    case 11:
      // "T"
      invalid = (dataByte != 'T');
      break;

    default:
      break;
  }

  if (invalid) {
    throw tr("FIT decoding error: file header signature mismatch. File is not FIT.");
  }

  if (offset == headerLength) {
    // end of header
    return eDecoderStateRecord;
  }
  return eDecoderStateFileHeader;
}
