/*=========================================================================

  Program:   ParaView
  Module:    vtkPVPluginFileLoader.cxx

  Copyright (c) Kitware, Inc.
  All rights reserved.
  See Copyright.txt or http://www.paraview.org/HTML/Copyright.html 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 "vtkPVPluginFileLoader.h"

#include "vtkObjectFactory.h"
#include "vtkPVPlugin.h"

std::vector<vtkPVPluginFileLoader::LoadPluginFileCallbackType> vtkPVPluginFileLoader::Callbacks;
std::vector<std::pair<std::string, std::string>> vtkPVPluginFileLoader::PluginPrefixAndExtensions;



vtkStandardNewMacro(vtkPVPluginFileLoader);
//----------------------------------------------------------------------------
vtkPVPluginFileLoader::vtkPVPluginFileLoader()
{
}

//----------------------------------------------------------------------------
vtkPVPluginFileLoader::~vtkPVPluginFileLoader()
{
}

  // * iterate over all registered PluginPrefixAndExtensions
  //    - convert the plugin name to a filename, as defined
  //    - locate plugin file using the filename
  //    - if found, iterate over all registered Callbacks
  //        + call callback to attempt to load the plugin file.
  //        + on success, import the plugin.

//----------------------------------------------------------------------------
std::string vtkPVPluginFileLoader::LocatePlugin(const char* pluginname)
{
  vtkNew<vtkResourceFileLocator> locator;

  // Need to support:
  // 1. relative to executable in ParaView specific locations
  // 2. relative to paraview-shared libraries in ParaView specific locations
  // 3. relative to executable in custom app specific locations
  // 3. relative to custom-app shared libraries in custom app specific locations

  // Our plan:
  // 1. user registers custom anchor locations. default is ParaView shared lib
  //    location (or executable in static builds). user can add anchor location
  //    using their app specific shared lib, to make it robust.
  // 2. user can register custom landmark prefixes.

  // * iterate over all registered PluginPrefixAndExtensions
  //    - convert the plugin name to a filename, as defined
  //    - locate plugin file using the filename
  for (auto& prefix_n_ext : vtkPVPluginFileLoader::PluginPrefixAndExtensions)
  {
    std::ostringstream str;
    str << prefix_n_ext.first << pluginname << prefix_n_ext.second;

    const auto landmark = str.str();
//    const auto landmark_search_prefixes = this->GetPluginPrefixes

  }
}


//----------------------------------------------------------------------------
int vtkPVPluginFileLoader::RegisterLoadPluginFileCallback(LoadPluginFileCallbackType callback)
{
  size_t index = vtkPVPluginFileLoader::Callbacks.size();
  vtkPVPluginFileLoader::Callbacks.push_back(callback);
  return static_cast<int>(index);
}

//----------------------------------------------------------------------------
void vtkPVPluginFileLoader::UnregisterLoadPluginFileCallback(int id)
{
  if (id >=0 && id < static_cast<int>(vtkPVPluginFileLoader::Callbacks.size()))
  {
    auto iter = vtkPVPluginFileLoader::Callbacks.begin();
    std::advance(iter, id);
    vtkPVPluginFileLoader::Callbacks.erase(iter);
  }
}

//----------------------------------------------------------------------------
std::shared_ptr<vtkPVPlugin> vtkPVPluginFileLoader::CallPluginLoaderCallbacks(const char* nameOrFile)
{
  auto &callbackVector = vtkPVPluginFileLoader::Callbacks;
  for (auto iter = callbackVector.rbegin(); iter != callbackVector.rend(); ++iter)
  {
    if (auto plugin = (*iter)(nameOrFile))
    {
      return plugin;
    }
  }

  return nullptr;
}

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