// SPDX-FileCopyrightText: Copyright (c) Kitware Inc.
// SPDX-License-Identifier: BSD-3-Clause
#include "vtkPVMemoryUseInformation.h"

#include "vtkClientServerStream.h"
#include "vtkObjectFactory.h"
#include "vtkProcessModule.h"

#include <vtksys/SystemInformation.hxx>

#include <iostream>

// #define vtkPVMemoryUseInformationDEBUG

#define vtkVerifyParseMacro(_call, _field)                                                         \
  if (!(_call))                                                                                    \
  {                                                                                                \
    vtkErrorMacro("Error parsing " _field ".");                                                    \
    return;                                                                                        \
  }

//----------------------------------------------------------------------------
vtkStandardNewMacro(vtkPVMemoryUseInformation);

//----------------------------------------------------------------------------
vtkPVMemoryUseInformation::vtkPVMemoryUseInformation() = default;

//----------------------------------------------------------------------------
vtkPVMemoryUseInformation::~vtkPVMemoryUseInformation() = default;

//----------------------------------------------------------------------------
void vtkPVMemoryUseInformation::CopyFromObject(vtkObject* obj)
{
  (void)obj;

  this->MemInfos.clear();

  MemInfo info;

  vtksys::SystemInformation sysInfo;

  info.ProcessType = vtkProcessModule::GetProcessType();
  info.Rank = vtkProcessModule::GetProcessModule()->GetPartitionId();
  info.ProcMemUse = sysInfo.GetProcMemoryUsed();
  info.HostMemUse = sysInfo.GetHostMemoryUsed();

#ifdef vtkPVMemoryUseInformationDEBUG
  info.Print();
#endif

  this->MemInfos.push_back(info);
}

//----------------------------------------------------------------------------
void vtkPVMemoryUseInformation::AddInformation(vtkPVInformation* pvinfo)
{
  vtkPVMemoryUseInformation* info = dynamic_cast<vtkPVMemoryUseInformation*>(pvinfo);

  if (!info)
  {
    return;
  }

  this->MemInfos.insert(this->MemInfos.end(), info->MemInfos.begin(), info->MemInfos.end());
}

//----------------------------------------------------------------------------
void vtkPVMemoryUseInformation::CopyToStream(vtkClientServerStream* css)
{
  css->Reset();

  size_t count = this->MemInfos.size();

  *css << vtkClientServerStream::Reply << count;

  for (size_t i = 0; i < count; ++i)
  {
    *css << this->MemInfos[i].ProcessType << this->MemInfos[i].Rank << this->MemInfos[i].ProcMemUse
         << this->MemInfos[i].HostMemUse;
  }

  *css << vtkClientServerStream::End;
}

//----------------------------------------------------------------------------
void vtkPVMemoryUseInformation::CopyFromStream(const vtkClientServerStream* css)
{
  int offset = 0;
  size_t count = 0;

  vtkVerifyParseMacro(css->GetArgument(0, offset, &count), "count");
  ++offset;

  this->MemInfos.resize(count);

  for (size_t i = 0; i < count; ++i)
  {
    vtkVerifyParseMacro(css->GetArgument(0, offset, &MemInfos[i].ProcessType), "ProcessType");
    ++offset;

    vtkVerifyParseMacro(css->GetArgument(0, offset, &MemInfos[i].Rank), "Rank");
    ++offset;

    vtkVerifyParseMacro(css->GetArgument(0, offset, &MemInfos[i].ProcMemUse), "ProcMemUse");
    ++offset;

    vtkVerifyParseMacro(css->GetArgument(0, offset, &MemInfos[i].HostMemUse), "HostMemUse");
    ++offset;
  }
}

//----------------------------------------------------------------------------
void vtkPVMemoryUseInformation::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
}

//----------------------------------------------------------------------------
void vtkPVMemoryUseInformation::MemInfo::Print()
{
  std::cerr << "ProcessType=" << this->ProcessType << endl
            << "Rank=" << this->Rank << endl
            << "ProcMemUse=" << this->ProcMemUse << endl
            << "HostMemUse=" << this->HostMemUse << endl;
}
