/* Distributed under the Apache License, Version 2.0.
   See accompanying NOTICE file for details.*/

#pragma once

#include "LBM.h"
#include "LBMUtils.h"
#include <vtkPolyDataNormals.h>
#include <vtkRectilinearGrid.h>
#include <vtkSmartPointer.h>

namespace LBM
{
  namespace VTK
  {
  LBM_DECL bool WriteVTP(std::string const& filename, vtkSmartPointer<vtkPolyData> pd);

  LBM_DECL bool FromVTR(vtkSmartPointer<vtkRectilinearGrid> vtr, LBM::Run& lbm);
  LBM_DECL bool ReadVTR(std::string const& filename, LBM::Run& lbm);
  LBM_DECL vtkSmartPointer<vtkRectilinearGrid> ReadVTR(std::string const& filename);

  LBM_DECL vtkSmartPointer<vtkRectilinearGrid> ToVTR(LBM::Run const& lbm);
  LBM_DECL bool WriteVTR(std::string const& filename, LBM::Run const& lbm);
  LBM_DECL bool WriteVTR(std::string const& filename, vtkSmartPointer<vtkRectilinearGrid> vtr);

  LBM_DECL bool CheckVTR(LBM::Run const& lbm);

  LBM_DECL vtkSmartPointer<vtkPolyData> ExtractSurface(vtkSmartPointer<vtkRectilinearGrid> vtr, int label);
  LBM_DECL vtkSmartPointer<vtkPolyData> ExtractSurface(vtkSmartPointer<vtkRectilinearGrid> vtr, int min_label, int max_label);

  struct LBM_DECL FlowMetrics : public LBM::FlowMetrics
  {
    vtkSmartPointer<vtkPolyData> inlet_surface;
    vtkSmartPointer<vtkPolyData> outlet_surface;
    vtkSmartPointer<vtkPolyData> wall_surface;
  };
  LBM_DECL std::unique_ptr<LBM::VTK::FlowMetrics> ComputeMetrics(LBM::Run const& lbm);
  LBM_DECL bool WriteMetrics(std::string const& base_name, LBM::VTK::FlowMetrics const& m);

  struct CSVPlotSource
  {
    CSVPlotSource(std::string const& name, const LBM::CSV& data, 
                  double red, double green, double blue, float width, int pen_type=1) : csv(data), name(name)
    {
      r = red;
      g = green;
      b = blue;
      w = width;
      p = pen_type;
    }
    ~CSVPlotSource() = default;
    const LBM::CSV& csv;
    double          r=0, g=0, b=0;
    float           w=2;
    int             p=1;
    std::string     name;
  };
  LBM_DECL bool PlotCSV(std::string const& base_name, std::vector<CSVPlotSource>const& srcs, Logger& log);
  LBM_DECL bool PlotCSV(std::string const& base_name, std::vector<CSVPlotSource>const& srcs, bool const_y_axis, Logger& log);

  LBM_DECL bool TestCSVPlot();

  // Cell labels used in VTR
  static constexpr char const* SOURCE_LABELS = "Source Labels";
  static constexpr char const* BOUNDARY_LABELS = "Boundary Labels";
  static constexpr char const* PRESSURE = "Pressure";
  static constexpr char const* X_FLOW = "Velocity in X direction";
  static constexpr char const* Y_FLOW = "Velocity in Y direction";
  static constexpr char const* Z_FLOW = "Velocity in Z direction";
  static constexpr char const* TEMPERATURE = "Temperature";
  static constexpr char const* STRESS = "Wall Shear Stress";
  // Expanded Results
  static constexpr char const* XY_STRESS = "Sigma_xy component";
  static constexpr char const* XZ_STRESS = "Sigma_xz component";
  static constexpr char const* YZ_STRESS = "Sigma_yz component";
  static constexpr char const* XX_STRESS = "Sigma_xx component";
  static constexpr char const* YY_STRESS = "Sigma_yy component";
  static constexpr char const* ZZ_STRESS = "Sigma_zz component";
  static constexpr char const* LEGACY_STRESS = "Legacy Wall Shear Stress";
}
}