//=========================================================================
//  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/rggPhraseModel.h"

#include "smtk/view/ComponentPhraseContent.h"
#include "smtk/view/DescriptivePhrase.h"
#include "smtk/view/QueryFilterSubphraseGenerator.h"
#include "smtk/view/ObjectGroupPhraseContent.h"
#include "smtk/view/PhraseListContent.h"

#include "smtk/operation/Manager.h"

#include "smtk/attribute/Attribute.h"
#include "smtk/attribute/ComponentItem.h"

#include "smtk/resource/Component.h"

#include <algorithm> // for std::sort
#include <iostream>

namespace smtk
{
namespace session
{
namespace rgg
{

rggPhraseModel::rggPhraseModel()
  : m_root(smtk::view::DescriptivePhrase::create())
{
}

rggPhraseModel::rggPhraseModel(const smtk::view::Configuration* config, smtk::view::Manager* manager)
  : Superclass(config, manager)
  , m_root(smtk::view::DescriptivePhrase::create())
{
  auto generator = this->configureSubphraseGenerator(config, manager);
  m_root->setDelegate(generator);
}

rggPhraseModel::~rggPhraseModel()
{
  this->resetSources();
}

smtk::view::DescriptivePhrasePtr rggPhraseModel::root() const
{
  return m_root;
}

void rggPhraseModel::handleResourceEvent(const Resource& rsrc, smtk::resource::EventType event)
{
  if (event == smtk::resource::EventType::ADDED)
  {
    this->processResource(rsrc, true);
  }
}

void rggPhraseModel::handleCreated(const smtk::resource::PersistentObjectSet& createdObjects)
{
  // TODO: Instead of looking for new resources (which perhaps we should leave to the
  //       handleResourceEvent()), we should optimize by adding new components to the
  //       root phrase if they pass m_componentFilters.
  for (const auto& obj : createdObjects)
  {
    auto comp = std::dynamic_pointer_cast<smtk::resource::Component>(obj);
    if (comp == nullptr)
    {
      continue;
    }
    smtk::resource::ResourcePtr rsrc = comp->resource();
    this->processResource(*rsrc, true);
  }

  // Finally, call our subclass method to deal with children of the root element
  this->PhraseModel::handleCreated(createdObjects);
}

void rggPhraseModel::processResource(const Resource& rsrc, bool adding)
{
  if (adding)
  {
    this->populateRoot();
  }
  else
  {
    // FIXME: Visit all, not immediate, children.
    smtk::view::DescriptivePhrases children(m_root->subphrases());
    children.erase(std::remove_if(children.begin(), children.end(),
        [&rsrc](const smtk::view::DescriptivePhrase::Ptr& phr) -> bool {
        return phr->relatedResource()->id() == rsrc.id();
        }),
      children.end());
    this->updateChildren(m_root, children, std::vector<int>());
  }
}

void rggPhraseModel::populateRoot()
{
  const std::string rsrcFilt("smtk::session::rgg::Resource");
  constexpr int typeNum = 4;
  const char* compFilts[typeNum][2] = {
    { "group[string{'selectable'='_rgg_core'}]", "core" },
    { "group[string{'selectable'='_rgg_assembly'}]", "assemblies" },
    { "aux_geom[string{'selectable'='_rgg_pin'}]", "pins" },
    { "aux_geom[string{'selectable'='_rgg_duct'}]", "ducts" }
  };

  smtk::view::DescriptivePhrases children;
  for (int ii = 0; ii < typeNum; ++ii)
  {
    children.emplace_back(
      smtk::view::ObjectGroupPhraseContent::createPhrase(
        compFilts[ii][1], rsrcFilt, compFilts[ii][0], m_root));
  }
  this->updateChildren(m_root, children, std::vector<int>());
}

}
}
}
