//=========================================================================
//  Copyright (c) Kitware, Inc.
//  All rights reserved.
//  See LICENSE.txt for details.
//
//  This software is distributed WITHOUT ANY WARRANTY; without even
//  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
//  PURPOSE.  See the above copyright notice for more information.
//=========================================================================
#include "smtk/session/rgg/json/jsonAssembly.h"

#include "smtk/session/rgg/json/jsonAssyExportParameters.h"

#include "smtk/common/json/jsonUUID.h"

#include<iostream>

namespace smtk
{
namespace session
{
namespace rgg
{
using json = nlohmann::json;

void to_json(json& j, const Assembly& assembly)
{
  j = {{"name", assembly.name()}, {"label", assembly.label()},
       {"color", assembly.color()}, {"associatedDuct", assembly.associatedDuct()},
       {"centerPin", assembly.centerPin()}, {"pitch", assembly.pitch()},
       {"latticeSize", assembly.latticeSize()},{"zAxis", assembly.zAxis()},
       {"rotate", assembly.rotate()},
        {"exportParameters", assembly.exportParams()}
      };
  // Nlohmann would serialie the schema map as json array instead of json object.
  // So we manually seralize it here.
  const Assembly::UuidToSchema& layout = assembly.layout();
  json uuidToSchemaJson = json::object();
  for (const auto& uToS : layout)
  {
    uuidToSchemaJson[uToS.first.toString()] = uToS.second;
  }
  j["layout"] = uuidToSchemaJson;

  const Assembly::UuidToCoordinates& uTC = assembly.entityToCoordinates();
  json uTCJson = json::object();
  for (const auto& uTCIter : uTC)
  {
    uTCJson[uTCIter.first.toString()] = uTCIter.second;
  }
  j["uuidToCoordinates"] = uTCJson;
}

void from_json(const json& j, Assembly& assembly)
{
  try
  {
    assembly.setName(j.at("name"));
    assembly.setLabel(j.at("label"));
    assembly.setColor(j.at("color"));
    assembly.setZAxis(j.at("zAxis"));
    assembly.setRotate(j.at("rotate"));
    assembly.setAssociatedDuct(j.at("associatedDuct"));
    assembly.setCenterPin(j.at("centerPin"));

    // Nlohmann cannot deserialize complicatd map properly.
    // So we manually deseralize it here.
    Assembly::UuidToSchema layout;
    json layoutJson = j.at("layout");
    for (const auto& iterL: layoutJson.items())
    {
      std::vector<std::pair<int, int>> schema = iterL.value();
      layout[iterL.key()] = schema;
    }
    assembly.setLayout(layout);

    Assembly::UuidToCoordinates uuidToCoords;
    json uTCJson = j.at("uuidToCoordinates");
    for (const auto& iterL: uTCJson.items())
    {
      std::vector<std::tuple<double, double, double>> coords = iterL.value();
      uuidToCoords[iterL.key()] = coords;
    }
    assembly.setEntityToCoordinates(uuidToCoords);

    std::pair<double, double> pitch = j.at("pitch");
    assembly.setPitch(pitch.first, pitch.second);
    std::pair<int, int> ls = j.at("latticeSize");
    assembly.setLatticeSize(ls.first, ls.second);

    AssyExportParameters ep = j.at("exportParameters");
    assembly.setExportParams(ep);
  }
  catch (json::exception& e)
  {
    std::cerr << e.what() << "\n";
    std::cerr << "RGG assembly does not have a valid json object" << std::endl;
    return;
  }
}

} // namespace rgg
} // namespace session
} // namespace smtk
