#include "stdafx.h"
#include "addon_repo.h"
#include "addon_manifest_loader.h"


Addon_repo::Addon_repo()
:
_log(Logger::default_instance())
{
}


Addon_repo::~Addon_repo()
{
}


void Addon_repo::purge()
{
  if (!_storage_dir.exists())
    return;

  if (!_storage_dir.remove(true))
    _log->throw_err("Failed to remove directory: " + _storage_dir.quoted_path() + ".");
  _addons.clear();
  load();
}


void Addon_repo::load()
{
  _storage_dir.ensure_exists();

  File_downloader fd;
  Addon_manifest_loader proc;
  proc.log(_log);
  proc.fd(&fd);
  proc.guid("{00000000-0000-0000-0000-000000000000}");
  proc.temp_dir(_temp_dir);
  proc.cached_addons(this);
  proc.lookup_cached_addons(true);

  // load all manifests from _storage_path
  std::list<File> fl;
  if (!_storage_dir.get_file_list(fl))
    _log->throw_err("Failed to access addons repo directory: " + _storage_dir.quoted_path() + ".");
  for (File_list::const_iterator i= fl.begin(), i_end= fl.end(); i != i_end; ++i)
    if ("xml" == i->ext())
      proc.parse_single_manifest(*i);
}


Addon * Addon_repo::find(const std::string &guid, const std::string min_version, const std::string max_version)
{
  std::pair<Addons_map::iterator, Addons_map::iterator> addons_range= _addons.equal_range(guid);
  if (_addons.end() == addons_range.first)
    return NULL;

  Addon::Version min_ver(min_version);
  Addon::Version max_ver(max_version);
  Addon *latest_addon= NULL;
  for (Addons_map::iterator i= addons_range.first, i_end= addons_range.second; i != i_end; ++i)
  {
    if (min_ver.valid() && (i->second.version < min_ver))
      continue;
    if (max_ver.valid() && (max_ver < i->second.version))
      continue;
    if (latest_addon && (i->second.version < latest_addon->version))
      continue;

    latest_addon= &i->second;
  }
  return latest_addon;
}


Addon * Addon_repo::find_or_create(const std::string &guid, const std::string version)
{
  Addon *addon= find(guid, version, version);
  if (addon)
    return addon;

  addon= &_addons.insert(std::make_pair(guid, Addon()))->second;
  addon->guid= guid;
  addon->version.parse_str(version);
  return addon;
}


void Addon_repo::add(Addon *addon)
{
  _addons.insert(std::make_pair(addon->guid, *addon));
}


void Addon_repo::remove(Addon *addon)
{
  _addons.erase(addon->guid);
}


void Addon_repo::get_dependent_addons(Addon *addon, Addons_list &addon_list)
{
  for (Addons_map::iterator i= _addons.begin(), i_end= _addons.end(); i != i_end; ++i)
    for (Addon::Dependencies::iterator d= i->second.dependencies.begin(), d_end= i->second.dependencies.end(); d != d_end; ++d)
      if (d->guid == addon->guid)
        addon_list.push_back(&i->second);
}


void Addon_repo::get_names(std::list<std::string> &guids, std::list<std::string> &names)
{
  for (Addons_map::iterator i= _addons.begin(), i_end= _addons.end(); i != i_end; ++i)
  {
    guids.push_back(i->first);
    names.push_back(i->second.full_name());
  }
}
