#ifndef PROGRESS_ARRAY_H
#define PROGRESS_ARRAY_H

#pragma once

#include "labeled_progress.h"

#include <QJsonArray>
#include <QJsonObject>
#include <QVector>

namespace ros_bridge {
//! @brief Namespace containing classes and methodes ros message generation.
namespace messages {
//! @brief Namespace containing classes and methodes for geometry_msgs
//! generation.
namespace nemo_msgs {
//! @brief Namespace containing methodes for nemo_msgs/progress_array message
//! generation.
namespace progress_array {

std::string messageType();

namespace {
const char *progressArrayKey = "progress_array";
} // namespace

//! @brief C++ representation of nemo_msgs/progress_array message
template <template <class, class...> class Container = QVector>
class GenericProgressArray {
public:
  typedef Container<labeled_progress::LabeledProgress> ContainerType;
  GenericProgressArray() {}

  ContainerType &progress_array() { return _progres_array; }

  const ContainerType &progress_array() const { return _progres_array; }

  void setProgressArray(const ContainerType &c) { _progres_array = c; }

protected:
  Container<labeled_progress::LabeledProgress> _progres_array;
};

typedef GenericProgressArray<> ProgressArray;

template <class Array> bool toJson(const Array &array, QJsonObject &value) {
  QJsonArray jsonArray;

  for (const auto &lp : array.progress_array()) {
    QJsonObject jsonLp;
    if (labeled_progress::toJson(lp, jsonLp)) {
      jsonArray.append(std::move(jsonLp));
    } else {
      return false;
    }
  }
  value[progressArrayKey] = std::move(jsonArray);
  return true;
}

template <class Array> bool fromJson(const QJsonObject &value, Array &p) {
  if (!value.contains(progressArrayKey) || !value[progressArrayKey].isArray()) {
    return false;
  }

  const auto jsonArray = value[progressArrayKey].toArray();
  p.progress_array().clear();
  p.progress_array().reserve(jsonArray.size());
  for (long i = 0; i < jsonArray.size(); ++i) {
    labeled_progress::LabeledProgress lp;
    if (!jsonArray[i].isObject() ||
        !labeled_progress::fromJson(jsonArray[i].toObject(), lp)) {
      return false;
    } else {
      p.progress_array().push_back(lp);
    }
  }

  return true;
}

} // namespace progress_array
} // namespace nemo_msgs
} // namespace messages
} // namespace ros_bridge

#endif // PROGRESS_ARRAY_H
