//=========================================================================
//  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/Pin.h"
#include "smtk/session/rgg/json/jsonPin.h"

namespace smtk
{
namespace session
{
namespace rgg
{
using namespace smtk::model;
using json = nlohmann::json;
std::set<std::string> Pin::s_usedLabels;

struct Pin::Internal
{
  Internal()
  {
    this->cellMaterialIndex = 0; // no material
    this->cutAway = 0;
    this->zOrigin = 0;
    this->pieces.push_back(Pin::Piece());
    this->layerMaterials.push_back(Pin::LayerMaterial());
  }

  std::string name;
  std::string label;
  int cellMaterialIndex;
  FloatList color;
  bool cutAway;
  double zOrigin;
  std::vector<Piece> pieces;
  std::vector<LayerMaterial> layerMaterials;
};

Pin::Pin()
  : m_internal(std::make_shared<Internal>())
{
}

Pin::Pin(const std::string& name, const std::string& label)
  : m_internal(std::make_shared<Internal>())
{
  m_internal->name = name;
  m_internal->label = label;
  s_usedLabels.insert(label);
}

Pin::~Pin()
{
}

bool Pin::isAnUniqueLabel(const std::string& label)
{
  return (Pin::s_usedLabels.find(label) == Pin::s_usedLabels.end()) ?
        true : false;
}

std::string Pin::generateUniqueLabel()
{
  int count = 0;
  std::string label = "PC0";
  while (Pin::s_usedLabels.find(label) != Pin::s_usedLabels.end())
  {
    count++;
    label = "PC" + std::to_string(count);
  }
  return label;
}

const std::string& Pin::name() const
{
  return m_internal->name;
}

const std::string& Pin::label() const
{
  return m_internal->label;
}

const int& Pin::cellMaterialIndex() const
{
  return m_internal->cellMaterialIndex;
}

const FloatList& Pin::color() const
{
  return m_internal->color;
}

bool Pin::isCutAway() const
{
  return m_internal->cutAway;
}

const double& Pin::zOrigin() const
{
  return m_internal->zOrigin;
}

std::vector<Pin::Piece>& Pin::pieces()
{
  return this->m_internal->pieces;
}

const std::vector<Pin::Piece>& Pin::pieces() const
{
  return this->m_internal->pieces;
}

std::vector<Pin::LayerMaterial>& Pin::layerMaterials()
{
  return this->m_internal->layerMaterials;
}

const std::vector<Pin::LayerMaterial>& Pin::layerMaterials() const
{
  return this->m_internal->layerMaterials;
}


void Pin::setName(const std::string& name)
{
  m_internal->name = name;
}

bool Pin::setLabel(const std::string& label)
{
  m_internal->label = label;
  s_usedLabels.insert(label);
  return true;
}

void Pin::setCellMaterialIndex(const int& index)
{
  m_internal->cellMaterialIndex = index;
}

void Pin::setColor(const FloatList& color)
{
  m_internal->color = color;
}

void Pin::setCutAway(bool cutAway)
{
  m_internal->cutAway = cutAway;
}

void Pin::setZOrigin(const double& zOrigin)
{
  m_internal->zOrigin = zOrigin;
}

void Pin::setPieces(const std::vector<Piece>& pieces)
{
  m_internal->pieces = pieces;
}

void Pin::setLayerMaterials(const std::vector<LayerMaterial>& lm)
{
  m_internal->layerMaterials = lm;
}

bool Pin::operator ==(const Pin& other) const
{
  json thisPin = *this;
  json otherPin = other;
  return thisPin == otherPin;
}

bool Pin::operator !=(const Pin& other) const
{
  return !(*this == other);
}

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