// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//

BALL_INLINE 
void File::clear()
{
	File::close();
	name_ = "";
}

BALL_INLINE 
const String& File::getName() const
{
	return name_;
}

BALL_INLINE 
void File::setName(const String& name)
{
	File::close();
	name_ = name;
	FileSystem::canonizePath(name_);
}


BALL_INLINE 
File::OpenMode File::getOpenMode() const
{
	return open_mode_;
}

BALL_INLINE 
File::Type File::getType(bool trace_link) const
{
	return File::getType(name_, trace_link);
}

BALL_INLINE 
bool File::copyTo(const String& destination_name, Size buffer_size)
{
	return File::copy(name_, destination_name, buffer_size);
}

BALL_INLINE 
bool File::remove(String name)
{
	FileSystem::canonizePath(name);
#ifdef BALL_COMPILER_MSVC
	return (::_unlink(name.c_str()) == 0);
#else
	return (::unlink(name.c_str()) == 0);
#endif
}

BALL_INLINE 
bool File::remove() 
{
#ifdef BALL_COMPILER_MSVC
	File::close();
#endif
	return File::remove(name_);
}

BALL_INLINE 
bool File::move(const String& source_name, const String& destination_name)
{
	if (File::copy(source_name, destination_name))
	{
		return File::remove(source_name);
	}
	return false;
}

BALL_INLINE 
bool File::moveTo(const String& destination_name)
{
#ifdef BALL_COMPILER_MSVC
	File::close();
#endif
	if (File::move(name_, destination_name))
	{
		name_ = destination_name;
		File::reopen();
		return true;
	}
	return false;
}

BALL_INLINE 
bool File::isAccessible(String name)
{
	FileSystem::canonizePath(name);
#ifdef BALL_COMPILER_MSVC
	return (::_access_s(name.c_str(),F_OK) == 0);
#else
	return (::access(name.c_str(), F_OK) == 0);
#endif
}

BALL_INLINE 
bool File::isAccessible() const
{
	return File::isAccessible(name_);
}


BALL_INLINE 
bool File::rename(String old_path, String new_path)
{
	FileSystem::canonizePath(old_path);
	FileSystem::canonizePath(new_path);

	if (!isAccessible(old_path))
	{
		throw (Exception::FileNotFound(__FILE__, __LINE__, old_path));
	}
#ifdef BALL_COMPILER_MSVC
	if(old_path==new_path) return true;
#endif

	return (::rename(old_path.c_str(), new_path.c_str()) == 0);
}

BALL_INLINE 
bool File::renameTo(const String& new_path)
{
#ifdef BALL_COMPILER_MSVC
	File::close();
#endif
	if (!File::rename(name_, new_path))
	{
#ifdef BALL_COMPILER_MSVC
		File::reopen();
#endif
		return false;
	}

	name_ = new_path;
#ifdef BALL_COMPILER_MSVC
	File::reopen();
#endif
	return true;
}

BALL_INLINE 
bool File::truncate(String path, Size size)
{
	if (!isAccessible(path))
	{
		throw (Exception::FileNotFound(__FILE__, __LINE__, path));
	}

	FileSystem::canonizePath(path);
#ifdef BALL_COMPILER_MSVC
	int fh = 0;
	if (_sopen_s(&fh, path.c_str(), (_O_RDWR | _O_CREAT), _SH_DENYWR, (_S_IREAD | _S_IWRITE)) != 0 || fh == -1)
	{
		return false;
	}

	int result = _chsize(fh, (long)size);
	_close(fh);
	return (result == 0);
#else
	return (::truncate(path.c_str(), (long)size) == 0);
#endif
}

BALL_INLINE 
bool File::truncate(Size size)
{
	return File::truncate(name_, size);
}

BALL_INLINE 
bool File::operator == (const File &file) const
{
	return (name_ == file.name_);
}

BALL_INLINE 
bool File::operator != (const File &file) const
{
	return (name_ != file.name_);
}

BALL_INLINE
bool File::isValid() const
{
	return (getName() != "" && ((File*)this)->std::fstream::good() );
}

BALL_INLINE 
bool File::isOpen() const
{
	return is_open_;
}

BALL_INLINE 
bool File::isClosed() const
{
	return !is_open_;
}

BALL_INLINE 
bool File::isCanonized() const 
{
	if (!isAccessible()) throw(Exception::FileNotFound(__FILE__, __LINE__, name_));

	String canonized_name(name_);

	FileSystem::canonizePath(canonized_name);

	return (name_ == canonized_name);
}

BALL_INLINE 
bool File::isReadable(String name)
{
	if (!File::isAccessible(name)) throw(Exception::FileNotFound(__FILE__, __LINE__, name));

	FileSystem::canonizePath(name);

#ifdef BALL_COMPILER_MSVC
	return (::_access_s(name.c_str(),R_OK) == 0);
#else
	return (::access(name.c_str(), R_OK) == 0);
#endif
}

BALL_INLINE 
bool File::isReadable() const 
{
	return File::isReadable(name_);
}

BALL_INLINE 
bool File::isWritable(String name)
{
	if (!File::isAccessible(name)) throw(Exception::FileNotFound(__FILE__, __LINE__, name));

	FileSystem::canonizePath(name);

#ifdef BALL_COMPILER_MSVC
	return (::_access_s(name.c_str(),W_OK) == 0);
#else
	return (::access(name.c_str(), W_OK) == 0);
#endif
}

BALL_INLINE 
bool File::isWritable() const 
{
	return File::isWritable(name_);
}

BALL_INLINE 
bool File::isExecutable(String name)
{
	if (!isAccessible(name)) throw(Exception::FileNotFound(__FILE__, __LINE__, name));

	FileSystem::canonizePath(name);
#ifdef BALL_COMPILER_MSVC
	return false;
#else
	return (::access(name.c_str(), X_OK) == 0);
#endif
}

BALL_INLINE 
bool File::isExecutable() const 
{
	return File::isExecutable(name_);
}

BALL_INLINE 
Size File::getSize(String name)
{
	File tmp(name);
	return tmp.getSize();
}

BALL_INLINE
std::fstream& File::getFileStream()
{
	return *this;
}

BALL_INLINE 
const String& File::getOriginalName() const
{
	return original_name_;
}
