/***************************************************************************

    supportware
    Copyright (C) 2001-2008 by c.holzheuer
    c.holzheuer@sourceworx.org

    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.

***************************************************************************/


#include <ddioinfo.h>
#include <ddiobuffer.h>
#include <dirent.h>
#include <sys/types.h>

using namespace std;



/**
	Default constructor	
*/

ddioinfo::ddioinfo()
: _entries(0)
{

}


/**
	Copy constructor.	
*/

ddioinfo::ddioinfo( const ddioinfo& src )
: ddioobject(), _entries(0)
{
	
	*this = src;
}


ddioinfo::ddioinfo( const ddstring& path )
: ddioobject(), _entries(0)
{
	init_path( path );
}

/**
	Assignment operator.
*/

ddioinfo& ddioinfo::operator=( const ddioinfo& src )
{
	if( this == &src )
		return *this;
	_data  = src._data;
	_flags = src._flags;
	_entries = 0;
	return *this;
}


/**
	Destructor.	
*/

ddioinfo::~ddioinfo()
{
  if( _entries )
  {
    //throw runtime_error( "FIX ME: LEAK!!! ddioinfo::~ddioinfo()" );
    /*
    for( size_t i=0; i<_entries->size(); ++i )
   		delete (*_entries)[i];
		*/
    delete _entries;
  }
}


	
	
size_t ddioinfo::size()
{
	// a file has no children
	if( !is_folder() || !_entries )	
		return 0;	
	return _entries->size();
}


/**
	Returns true if this directory conains "filename"
	@param filename the filename to look for.
*/
	
int ddioinfo::index_of( const ddstring& filename )
{
	if( !is_folder() || !_entries )
		return -1;
	return _entries->index_of( filename );
}

ddioinfo& ddioinfo::operator[]( size_t index )
{
	if( !_entries )
		throw runtime_error( "ddioinfo::operator[]( size_t index ): empty!" );
	return _entries->get_entry( index );
}

ddioinfo& ddioinfo::operator[]( const ddstring& filename )
{
	if( !_entries )
		throw runtime_error( "ddioinfo::operator[]( const ddstring& filename ): empty!" );
	return _entries->get_entry( filename );
}




/**
	updates the internal structure of directory entries.
	@see get_entries()
*/

void ddioinfo::init_entries( const ddstring& path, const ddstring& filter, bool do_append )
{	
	init_path( path );
	
	if( !_entries )
		_entries = new ddioinforow();
	else if( !do_append )
		_entries->clear();
	
	_data[ddioobject::url_fullpath].to_dir_name();
	
	DIR* dir = ::opendir ( get_full_path().c_str() );
	if( 0 == dir )
		throw runtime_error( "dddirinfo::open() failed: " + get_full_path() );
	
	// FIX! use reentrant version of readdir
	//int readdir_r ( drc, struct dirent *entry, struct dirent **result)
	struct dirent* entry = 0;
	
	
	// hack: skip . and ..
	// das haut nicht mehr hin da sich die reihenfolge geändert hat: . und ..
	// sind nicht mehr oben!!!!!!!!!!!!!!
	//::readdir(dir);
	//::readdir(dir);
	
	
	while( 0 != ( entry = ::readdir(dir) ) )
	{
		// filter
		ddstring tmpname = entry->d_name;
		if( tmpname == "." || tmpname == ".." )
			continue;
		if( filter.empty() || tmpname.rfind( filter ) != ddstring::npos )
		{
			ddioinfo* newitem = new ddioinfo( get_full_path()+tmpname );
			_entries->add_by_key( newitem->get_full_name(), newitem );
		}
	
	}
	::closedir( dir );
}




void ddioinfo::load_files( const ddstring& path, const ddstring& filter, bool do_append )
{
	init_entries( path, filter, do_append );
	//cout << "MAA: " << _entries->size() << endl;
	for( int i=0; i<_entries->size(); ++i )
	{
      if( (*_entries)[i]->load_file_content() < 0 )
   		throw runtime_error( "ddioinfo::load_files: not found: " + (*_entries)[i]->get_full_name() );
  }
}
  


/**
	Creates the data members from the source strings.
	@param	path 	the src  string
	@param 	base	   the base path (optional)
*/
	
bool ddioinfo::init_path( const ddstring& path )
{
  // FIX!
	//_data.clear();
	//_data.resize( url_field_size );
	
	if( path.size() >0 && path[0] != '/' )
		set_flag( ddioobject::url_is_relative  );
	_data[ddioobject::url_fullpath]  = path;

	// path is the path without file
	size_t pos = path.rfind( '/' );
	// path does exist
	if( pos != ddstring::npos && pos != 0 )
	{
		_data[ddioobject::url_path] = path.substr( 0, pos+1 );
		_data[ddioobject::url_file] = path.substr( pos+1 );
	}
	else   // path does not exist
	{
	 	_data[ddioobject::url_file] = path;
		_data[ddioobject::url_path] = path;
	}
	_data[ddioobject::url_path].to_dir_name();
	ddstring& src =_data[ddioobject::url_file];
	size_t nxt = src.rfind( '.' );
	if( nxt != ddstring::npos )
	{
		_data[ddioobject::url_file_type] = src.substr( nxt+1 );
		_data[ddioobject::url_file_body] = src.substr( 0, nxt );
	}
	else
	{
		_data[ddioobject::url_file_body] = src;
	}
	
	// cleanup
	if( _statbuf )
		delete _statbuf;
	_statbuf = 0;

	return true;
	
}

/**
	Dumps all fields for debugging purposes.
*/

void ddioinfo::dump() const
{
	ddioobject::dump();	
	if( 0 == _entries )
		return;	
	for( int i=0; i<_entries->size(); ++i )
		cout << (*_entries)[i]->get_full_name() << endl;
	
}



