//////////////////////////////////////////////////////////////////////////////
//
//   Copyright (C) 2002  by Diether Knof
//
//   This program is free software; you can redistribute it and/or 
//   modify it under the terms of the GNU General Public License as 
//   published by the Free Software Foundation; either version 2 of 
//   the License, or (at your option) any later version.
//
//   This program is distributed in the hope that it will be useful,
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//   GNU General Public License for more details. 
//   You can find this license in the file 'gpl.txt'.
//
//   You should have received a copy of the GNU General Public License
//   along with this program; if not, write to the Free Software
//   Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
//   MA  02111-1307  USA
//
//  Contact:
//    Diether Knof dknof@gmx.de
//
//////////////////////////////////////////////////////////////////////////////

#include "file.h"
#include "string.h"
#include "windows.h"

#include <sys/stat.h>
#if defined(LINUX) || defined(HPUX)
// for getpwent
#include <pwd.h>
#include <unistd.h>
#endif

using std::string;

namespace DK {
  namespace Utils {
    namespace File {

      /**
       **
       ** returns the home directory of the user
       **
       ** @param	-
       **
       ** @return	the home directory
       ** 
       ** @author	Diether Knof
       **
       ** @version	2003-10-30
       **
       **/
      string
	home_directory()
	{
#ifndef WINDOWS
	  if (getenv("HOME") != NULL)
	    return getenv("HOME");

	  struct passwd* pwd;
	  if ( (pwd = getpwuid(getuid())) != NULL )
	    return pwd->pw_dir;


#else  // !#ifndef WINDOWS
	    return DK::Utils::Windows::Reg_read(HKEY_CURRENT_USER,
						"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders",
						"AppData");
#endif // !#ifndef WINDOWS
	  return "";
	} // string home_directory()

      /**
       **
       ** returns the desktop directory of the user
       **
       ** @param	-
       **
       ** @return	the desktop directory
       ** 		empty string, if the directory does not exists
       ** 
       ** @author	Diether Knof
       **
       ** @version	2004-03-03
       **
       **/
      string
	desktop_directory()
	{
#ifdef WINDOWS
	  return DK::Utils::Windows::Reg_read(HKEY_CURRENT_USER,
					      "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders",
					      "Desktop");
#endif
#ifdef LINUX
	  if (DK::Utils::File::isdirectory(home_directory() + "/Desktop"))
	    return (home_directory() + "/Desktop");
#endif

	  return "";
	} // string desktop_directory()

      /**
       **
       ** remove 'depth' times the basename of 'filename'
       **
       ** @param	filename	the filename to be checked
       **
       ** @return	the dirname of 'filename'
       ** 
       ** @author	Diether Knof
       **
       ** @version	2003-03-30
       **
       **/
      string
	dirname(std::string const& filename, unsigned const depth)
	{
	  if (depth == 0)
	    return filename;
	  if (depth > 1)
	    return dirname(dirname(filename), depth - 1);

	  // search the last '/' and remove all from that position on
	  unsigned pos;
	  for (pos = filename.length(); pos > 0; pos--)
	    if (filename[pos - 1] == '/')
	      break;

	  if (pos == 0){
	    // the path does not contain a directory
	    return ".";
	  } else {
	    return string(filename, 0, pos - 1);
	  }
	} // string dirname(std::string const& filename, unsigned const depth = 1)

      /**
       **
       ** -> result
       **
       ** @param	filename	the filename to be checked
       ** @param	suffix		the suffix, that shall be removed
       **
       ** @return	the basename of 'filename' without 'suffix'
       ** 
       ** @author	Diether Knof
       **
       ** @version	2003-03-30
       **
       **/
      string
	basename(std::string const& filename, string const& suffix)
	{
	  // search the last '/' and remove all til that position
	  unsigned pos;
	  for (pos = filename.length(); pos > 0; pos--)
	    if (filename[pos - 1] == '/')
	      break;

	  if ((pos + suffix.length() + 1 <= filename.length())
	      && (string(filename, filename.length() - suffix.length() - 1,
			 string::npos)
		  == "." + suffix))
	    // the suffix exists
	    return string(filename,
			  pos,
			  filename.length() - pos - suffix.length() - 1);
	  else // if !(suffix exists)
	    return string(filename, pos, string::npos);

	} // string basename(std::string const& filename, string const& suffix = "")

      /**
       **
       ** -> result
       **
       ** @param	filename	the filename to be checked
       **
       ** @return	the extension of 'filename'
       ** 
       ** @author	Diether Knof
       **
       ** @version	2003-03-30
       **
       **/
      string
	extension(std::string const& filename)
	{
	  // search the last '/' and remove all til that position
	  unsigned pos;
	  for (pos = filename.length(); pos > 0; pos--)
	    if ((filename[pos - 1] == '/')
		|| (filename[pos - 1] == '.'))
	      break;

	  if ((pos == 0) || (filename[pos - 1] == '/')){
	    // the file does not contain an extension
	    return "";
	  } else {
	    return string(filename, pos, string::npos);
	  }
	} // string extension(std::string const& filename)

      /**
       **
       ** -> result
       **
       ** @param	name	the name to check
       **
       ** @return	whether 'name' is a file that exists
       ** 
       ** @author	Diether Knof
       **
       ** @version	2003-03-30
       **
       **/
      bool
	isfile(string const& name)
	{
	  struct stat status;

	  // look, whether the file exists
#ifdef LINUX
	  if (lstat(name.c_str(), &status) == -1)
#else
	    ;
	  if (stat(name.c_str(), &status) == -1)
#endif
	    return false;

	  return (S_ISREG(status.st_mode) ? true : false);
	} // bool isfile(string const& name)

      /**
       **
       ** -> result
       **
       ** @param	name	the name to check
       **
       ** @return	whether 'name' is a directory that exists
       ** 
       ** @author	Diether Knof
       **
       ** @version	2003-03-30
       **
       **/
      bool
	isdirectory(string const& name)
	{
	  struct stat status;

	  // look, whether the file exists
#ifdef LINUX
	  if (lstat(name.c_str(), &status) == -1)
#else
	    ;
	  if (stat(name.c_str(), &status) == -1)
#endif
	    return false;

	  return (S_ISDIR(status.st_mode) ? true : false);
	} // bool isdirectory(String const& name)


      /**
       **
       ** Linux: replayce '~/' with $HOME
       ** Windows: replace '~/' with HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVerson\Explorer\Shell Folders\AppData
       **
       ** @param	filename	filename to be expanded
       **
       ** @return	expanded filename
       ** 
       ** @author	Diether Knof
       **
       ** @version	2003-04-02
       **
       **/
      string
	filename_expand(string filename)
	// expands the filename: replaces '~/' by '$HOME/'
	{
	  if (filename.size() >= 2) {
	    if ((filename[0] == '~')
		&& (filename[1] == '/')) {
	      filename = home_directory() + string(filename, 1, string::npos);
#ifdef WINDOWS
	      DK::Utils::String::replace_all(filename, "\\", "/");
#endif // #ifdef WINDOWS
	    } // if ((filename[0] == '~') && (filename[1] == '/'))
	  } // if (filename.size() >= 2)

	  return filename;
	} // string filename_expand(string filename)

    } // namespace File
  } // namespace Utils
} // namespace DK
