/*------------------------------------------------------------------------------
 src/lib/dj/dir.cxx

 Copyright (c) 2004-2006 Darby Johnston.
 All rights reserved.
 Use is subject to license terms.
------------------------------------------------------------------------------*/

//#define DJ_DBG
#include "djDir.h"
#include <djUser.h>
#include <dirent.h>
#include <pwd.h>
#include <unistd.h>
#include <errno.h>

namespace dj {

void Dir::init()
{
  _absolute = false;
  _isValid = false;
}

Dir::Dir() { init(); }
Dir::Dir(const Str & in) { init(); set(in); }

void Dir::set(const Str & in)
{
  DJ_DBG_FNC("dj::Dir::set");
  DJ_DBG_PRN("in = " << in);
  
  _absolute = in.isNull() ? false : ('/' == in[0]);
  _path = split(in, '/');
  DJ_DBG_PRN("path = " << _path);
  DJ_DBG_PRN("absolute = " << _absolute);
  
  updateValid();
}

const List<FileInfo> Dir::itemList() const
{
  DJ_DBG_FNC("dj::Dir::itemList");
  
  List<FileInfo> out;
  
  Str path = get();
  if (path.isNull()) path = "./";
  DJ_DBG_PRN("path = " << path);
  
  DIR * dir = ::opendir(path.toAscii());
  if (dir) {
    while (struct dirent * it = readdir(dir)) {
      const Str name(it->d_name);
      if (Str(".") == name) continue;
      else if (Str("..") == name) continue;
      FileInfo fileInfo(path + name);
      fileInfo.stat();
      out += fileInfo;
    }
    ::closedir(dir);
  } else {
  
    //perror(0);
  }
  
  DJ_DBG_PRN("size = " << out.size());
  return out;
}

void Dir::cd(const Str & in)
{
  DJ_DBG_FNC("dj::Dir::cd");
  DJ_DBG_PRN("in = " << in);
  
  _path = dirPathFix(_path + split(in, '/'));
  updateValid();
}

void Dir::up()
{
  cd("..");
}

void Dir::home()
{
  const struct passwd * buf = ::getpwuid(userCurrent());
  set(buf->pw_dir);
}

void Dir::root()
{
  set("/");
}

const Str Dir::get() const
{
  Str out;
  if (_absolute) out += '/';
  out += join(_path, '/');
  if (out != Str("/") && out.size()) out += '/';
  return out;
}

void Dir::updateValid()
{
  DIR * dir = opendir(get().toAscii());
  if (dir) {
    ::closedir(dir);
    _isValid = true;
  } else
    _isValid = false;
}

const Str dirPathFix(const Str & in)
{
  return join(dirPathFix(split(in, '/')), '/');
}

const StrList dirPathFix(const StrList & in)
{
  DJ_DBG_FNC("dj::dirPathFix");
  DJ_DBG_PRN("in = " << in);
  
  StrList out;
  
  const Str dotDot("..");
  for (ConstStrListIt it = in; it.isValid(); ++it)
    if (dotDot == it() && out.size()) {
      if (out[out.size() - 1] != dotDot)
        out.shift();
      else
        out += it();
    } else
      out += it();
  
  DJ_DBG_PRN("out = " << out);
  return out;
}

const Str dirPathAbsolute(const Str & in)
{
  char tmp [DJ_CSTR_SIZE];
  if (! ::getcwd(tmp, DJ_CSTR_SIZE))
    tmp[0] = 0;
  
  chdir(in.toAscii());
  char cwd [DJ_CSTR_SIZE];
  if (! ::getcwd(cwd, DJ_CSTR_SIZE))
    cwd[0] = 0;
  
  ::chdir(tmp);
  return Str(cwd) + '/';
}

}
