#ifndef GNUPLOT_WRITER_1D_HPP
#define GNUPLOT_WRITER_1D_HPP

#include <output/WriterBase.hpp>

#include <algebra/TinyMatrix.hpp>
#include <algebra/TinyVector.hpp>
#include <output/OutputNamedItemValueSet.hpp>

class IMesh;

#include <string>

class GnuplotWriter1D : public WriterBase
{
 private:
  std::string _getDateAndVersionComment() const;

  std::string _getFilename() const;

  template <typename DataType>
  bool _is_cell_value(const CellValue<const DataType>&) const;

  template <typename DataType>
  bool _is_cell_value(const NodeValue<const DataType>&) const;

  template <typename DataType>
  bool _is_node_value(const CellValue<const DataType>&) const;

  template <typename DataType>
  bool _is_node_value(const NodeValue<const DataType>&) const;

  template <typename DataType, ItemType item_type>
  size_t _itemValueNbRow(const ItemValue<DataType, item_type>&) const;

  template <typename MeshType, ItemType item_type>
  void _writeItemValues(const std::shared_ptr<const MeshType>& mesh,
                        const OutputNamedItemValueSet& output_named_item_value_set,
                        std::ostream& fout) const;

  void _writePreamble(const OutputNamedItemValueSet& output_named_item_value_set, std::ostream& fout) const;

  template <typename MeshType>
  void _write(const std::shared_ptr<const MeshType>& mesh,
              const OutputNamedItemValueSet& output_named_item_value_set,
              double time) const;

 public:
  void writeMesh(const std::shared_ptr<const IMesh>& mesh) const final;

  void write(const std::vector<std::shared_ptr<const NamedDiscreteFunction>>& named_discrete_function_list,
             double time) const final;

  GnuplotWriter1D(const std::string& base_filename, const double time_period) : WriterBase(base_filename, time_period)
  {}

  ~GnuplotWriter1D() = default;
};

#endif   // GNUPLOT_WRITER_1D_HPP