//
// C++ Implementation: PresetLoader
//
// Description:
//
//
// Author: Carmelo Piccione <carmelo.piccione@gmail.com>, (C) 2007
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "PresetLoader.hpp"
#include "Preset.hpp"
#include "PresetFactory.hpp"
#include <iostream>
#include <sstream>
#include <set>

#ifdef LINUX
extern "C"
{
#include <errno.h>
}
#endif

#ifdef MACOS
extern "C"
{
#include <errno.h>
}
#endif

#include <cassert>
#include "fatal.h"

#include "Common.hpp"


PresetLoader::PresetLoader (int gx, int gy, std::string dirname = std::string())
 : _dirname (dirname),
   _dir (0)
{
  _presetFactoryManager.initialize (gx, gy);
  // Do one scan
  if (_dirname != std::string())
    rescan();
  else
    clear();
}

PresetLoader::~PresetLoader()
{
  if (_dir)
    closedir (_dir);
}

void
PresetLoader::setScanDirectory (std::string dirname)
{
  _dirname = dirname;
}


void
PresetLoader::rescan()
{
  // std::cerr << "Rescanning..." << std::endl;

  // Clear the directory entry collection
  clear();

  // If directory already opened, close it first
  if (_dir)
  {
    closedir (_dir);
    _dir = 0;
  }

  // Allocate a new a stream given the current directory name
  if ((_dir = opendir (_dirname.c_str())) == NULL)
  {
    handleDirectoryError();
    return; // no files loaded. _entries is empty
  }

  struct dirent         *dir_entry;
  std::set<std::string> alphaSortedFileSet;
  std::set<std::string> alphaSortedPresetNameSet;

  while ((dir_entry = readdir (_dir)) != NULL)
  {
    if (dir_entry->d_name == 0)
      continue;

    std::ostringstream  out;
    // Convert char * to friendly string
    std::string         filename (dir_entry->d_name);

    // Verify extension is projectm or milkdrop
    if (!_presetFactoryManager.extensionHandled (parseExtension (filename)))
      continue;

    if (filename.length() > 0  &&  filename[0] == '.')
      continue;

    // Create full path name
    out << _dirname << PATH_SEPARATOR << filename;

    // Add to our directory entry collection
    alphaSortedFileSet.insert (out.str());
    alphaSortedPresetNameSet.insert (filename);

    // the directory entry struct is freed elsewhere
  }

  // Push all entries in order from the file set to the file entries member (which is an indexed vector)
  for (std::set<std::string>::iterator pos = alphaSortedFileSet.begin();
       pos != alphaSortedFileSet.end();
       ++pos)
  {
    _entries.push_back (*pos);
  }

  // Push all preset names in similar fashion
  for (std::set<std::string>::iterator pos = alphaSortedPresetNameSet.begin();
       pos != alphaSortedPresetNameSet.end();
       ++pos)
  {
    _presetNames.push_back (*pos);
  }

  // Give all presets equal rating of 3 - why 3? I don't know
  _ratings = std::vector<RatingList>(TOTAL_RATING_TYPES, RatingList (_presetNames.size(), 3));
  _ratingsSums = std::vector<int>(TOTAL_RATING_TYPES, 3 * _presetNames.size());


  assert (_entries.size() == _presetNames.size());
}


std::auto_ptr<Preset>
PresetLoader::loadPreset (unsigned int index)  const
{
  // Check that index isn't insane
  assert (index >= 0);
  assert (index < _entries.size());

  // Return a new autopointer to a preset
  const std::string extension = parseExtension (_entries[index]);

  return _presetFactoryManager
         .factory (extension)
         .allocate (_entries[index], _presetNames[index]);
}


std::auto_ptr<Preset>
PresetLoader::loadPreset (const std::string & url)  const
{
  // Return a new autopointer to a preset
  const std::string extension = parseExtension (url);

  /// @bug probably should not use url for preset name
  return _presetFactoryManager
         .factory (extension)
         .allocate (url, url);
}

void
PresetLoader::handleDirectoryError()
{

#ifdef WIN32
  std::cerr << "[PresetLoader] warning: errno unsupported on win32 platforms. fix me" << std::endl;
#else

  switch (errno) {
  case ENOENT:
    std::cerr << "[PresetLoader] ENOENT error. The path \""
              << this->_dirname
              << "\" probably does not exist. \"man open\" for more info."
              << std::endl;
    break;
  case ENOMEM:
    std::cerr << "[PresetLoader] out of memory! Are you running Windows?"
              << std::endl;
    abort();
  case ENOTDIR:
    std::cerr << "[PresetLoader] directory specified is not a preset directory! Trying to continue..."
              << std::endl;
    break;
  case ENFILE:
    std::cerr << "[PresetLoader] Your system has reached its open file limit. Trying to continue..."
              << std::endl;
    break;
  case EMFILE:
    std::cerr << "[PresetLoader] too many files in use by projectM! Bailing!"
              << std::endl;
    break;
  case EACCES:
    std::cerr << "[PresetLoader] permissions issue reading the specified preset directory."
              << std::endl;
    break;
  default:
    break;
  }
#endif
}

void
PresetLoader::setRating (unsigned int index, int rating, const PresetRatingType ratingType)
{
  assert (index >=0);

  const unsigned int ratingTypeIndex = static_cast<unsigned int>(ratingType);
  assert (index < _ratings[ratingTypeIndex].size());

  _ratingsSums[ratingTypeIndex] -= _ratings[ratingTypeIndex][index];

  _ratings[ratingTypeIndex][index] = rating;
  _ratingsSums[ratingType] += rating;
}


unsigned int
PresetLoader::addPresetURL (
const std::string       & url,
const std::string       & presetName,
const std::vector<int>  & ratings
)
{
  _entries.push_back (url);
  _presetNames.push_back (presetName);

  assert (ratings.size() == TOTAL_RATING_TYPES);
  assert (ratings.size() == _ratings.size());

  for (int i = 0;  i < _ratings.size();  i++)
    _ratings[i].push_back (ratings[i]);

  for (int i = 0;  i < ratings.size();  i++)
    _ratingsSums[i] += ratings[i];

  return _entries.size() - 1;
}

void
PresetLoader::removePreset (unsigned int index)
{
  _entries.erase (_entries.begin() + index);
  _presetNames.erase (_presetNames.begin() + index);

  for (int i = 0;  i < _ratingsSums.size();  i++) {
    _ratingsSums[i] -= _ratings[i][index];
    _ratings[i].erase (_ratings[i].begin() + index);
  }
}

const std::string &
PresetLoader::getPresetURL (unsigned int index) const
{
  return _entries[index];
}

const std::string &
PresetLoader::getPresetName (unsigned int index) const
{
  return _presetNames[index];
}

int
PresetLoader::getPresetRating (
unsigned int            index,
const PresetRatingType  ratingType
) const
{
  return _ratings[ratingType][index];
}

const std::vector<RatingList> &
PresetLoader::getPresetRatings() const
{
  return _ratings;
}

const std::vector<int> &
PresetLoader::getPresetRatingsSums() const
{
  return _ratingsSums;
}

void
PresetLoader::setPresetName (unsigned int index, std::string name)
{
  _presetNames[index] = name;
}

void
PresetLoader::insertPresetURL (
unsigned int      index,
const std::string & url,
const std::string & presetName,
const RatingList  & ratings
)
{
  _entries.insert (_entries.begin() + index, url);
  _presetNames.insert (_presetNames.begin() + index, presetName);

  for (int i = 0;  i < _ratingsSums.size();  i++) {
    _ratingsSums[i] += _ratings[i][index];
    _ratings[i].insert (_ratings[i].begin() + index, ratings[i]);
  }

  assert (_entries.size() == _presetNames.size());
}
