/* Blinker
   Copyright 2011-2019 Stefan Schuermans <stefan@blinkenarea.org>
   Copyleft GNU public license - http://www.gnu.org/copyleft/gpl.html
   a blinkenarea.org project */

#include <dirent.h>
#include <string>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include "Directory.h"
#include "File.h"

namespace Blinker {

/**
 * @brief constructor from path
 * @param[in] path path to directory
 */
Directory::Directory(const std::string &path):
  File(path)
{
  if (m_path.empty() || m_path.at(m_path.length() - 1) != '/')
    m_path += '/';
}

/**
 * @brief get list of entries in directory
 * @param[in] type type of directory entries to return
 * @param[out] entries list of directory entries
 */
void Directory::getEntries(Type type, std::list<std::string> &entries) const
{
  entries.clear();

  if (m_path.empty())
    return;
  DIR *dir = opendir(m_path.c_str());
  if (!dir)
    return;

  struct dirent *dirent;
  while ((dirent = readdir(dir))) {
    if (strcmp(dirent->d_name, ".") && strcmp(dirent->d_name, "..") ) {

      struct stat s;
      if (stat((m_path + dirent->d_name).c_str(), &s))
        continue; // cannot stat -> silently ignore

      bool ok = false;
      switch (type) {
        case TypeSubdir: ok = S_ISDIR(s.st_mode); break;
        case TypeFile:   ok = S_ISREG(s.st_mode); break;
      }
      if (ok)
        entries.push_back(dirent->d_name);

    } // if ! "." && ! ".."
  } // while dirent

  closedir(dir);

  entries.sort();
}

/**
 * @brief get subdirectory
 * @param[in] name of subdirectory
 * @return subdirectory object
 */
Directory Directory::getSubdir(const std::string &name) const
{
  return Directory(m_path + name);
}

/**
 * @brief get file in directory
 * @param[in] name of file
 * @return file object
 */
File Directory::getFile(const std::string &name) const
{
  return File(m_path + name);
}

} // namespace Blinker

