#include "stdafx.h"

#include "FileInfo.hpp"

#include "Utility.hpp"


/////////////////////////////////

CFileInfo::CFileInfo()
	: name_(_T(""))
	, attributes_(0)
	, size_(0)
	, bExist_(false)
	, detectModified_(false)
	, detectBegin_(FILETIME())
	, deletePending_(false)
	, deletePendingBegin_(FILETIME())
	, runCount_(0)
{
	FILETIME ft = {0};
	writetime_ = ft;
}

CFileInfo::CFileInfo(const WIN32_FIND_DATA& v_finddata, bool v_modified, bool v_exists)
	: name_(v_finddata.cFileName)
	, writetime_(v_finddata.ftLastWriteTime)
	, attributes_(v_finddata.dwFileAttributes)
	, size_(GetFileSize(v_finddata))
	, bExist_(v_exists)
	, detectModified_(v_modified)
	, detectBegin_(FILETIME())
	, deletePending_(false)
	, deletePendingBegin_(FILETIME())
	, runCount_(0)
{
}

CFileInfo::CFileInfo(const CFileInfo& v_other)
	: name_(v_other.name_)
	, writetime_(v_other.writetime_)
	, attributes_(v_other.attributes_)
	, bExist_( v_other.bExist_)
	, detectModified_(v_other.detectModified_)
	, detectBegin_(v_other.detectBegin_)
	, size_(v_other.size_)
	, deletePending_(v_other.deletePending_)
	, deletePendingBegin_(v_other.deletePendingBegin_)
	, runCount_(v_other.runCount_)
{
}

CFileInfo& CFileInfo::operator=(const CFileInfo& v_other)
{
	if (this == &v_other) {
		return *this;
	}

	name_ = v_other.name_;
	writetime_ = v_other.writetime_;
	attributes_ = v_other.attributes_;
	bExist_ = v_other.bExist_;
	detectModified_ = v_other.detectModified_;
	detectBegin_ = v_other.detectBegin_;
	size_ = v_other.size_;
	deletePending_ = v_other.deletePending_;
	deletePendingBegin_ = v_other.deletePendingBegin_;
	runCount_ = v_other.runCount_;

	return *this;
}

CFileInfo::~CFileInfo()
{
}

int CFileInfo::compare(const CFileInfo& other) const
{
	LONG ret = CompareFileTime(&writetime_, &other.writetime_);
	if (ret == 0) {
		ret = name_.compare(other.name_);
	}
	return ret == 0 ? 0 : (ret < 0 ? -1 : 1);
}


void CFileInfo::Save(CObjectWriter& writer) const
{
	writer.WriteString(name_);
	writer.WriteFILETIME(writetime_);
	writer.WriteDWORD(attributes_);
	writer.WriteBool(bExist_);
	writer.WriteBool(detectModified_);
	writer.WriteFILETIME(detectBegin_);
	writer.WriteInt64(size_);
	writer.WriteBool(deletePending_);
	writer.WriteFILETIME(deletePendingBegin_);
	writer.WriteDWORD(runCount_);
}

void CFileInfo::Load(CObjectReader& reader)
{
	reader.ReadString(name_);
	reader.ReadFILETIME(writetime_);
	attributes_ = reader.ReadDWORD();
	bExist_ = reader.ReadBool();
	detectModified_ = reader.ReadBool();
	reader.ReadFILETIME(detectBegin_);
	size_ = reader.ReadInt64();
	deletePending_ = reader.ReadBool();
	reader.ReadFILETIME(deletePendingBegin_);
	runCount_ = reader.ReadDWORD();
}


tstring CFileInfo::str() const
{
	SYSTEMTIME systime = {0};
	FILETIME localtime = {0};
	FileTimeToLocalFileTime(&writetime_, &localtime);
	FileTimeToSystemTime(&localtime, &systime);

	TCHAR szAttributes[] = _T("_______");

	if (attributes_ & FILE_ATTRIBUTE_ARCHIVE) {
		szAttributes[0] = 'A';
	}
	if (attributes_ & FILE_ATTRIBUTE_COMPRESSED) {
		szAttributes[1] = 'C';
	}
	if (attributes_ & FILE_ATTRIBUTE_ENCRYPTED) {
		szAttributes[2] = 'E';
	}
	if (attributes_ & FILE_ATTRIBUTE_READONLY) {
		szAttributes[3] = 'R';
	}
	if (attributes_ & FILE_ATTRIBUTE_HIDDEN) {
		szAttributes[4] = 'H';
	}
	if (attributes_ & FILE_ATTRIBUTE_SPARSE_FILE) {
		szAttributes[5] = 'p';
	}
	if (attributes_ & FILE_ATTRIBUTE_SYSTEM) {
		szAttributes[6] = 'S';
	}
	szAttributes[7] = 0;

	return ToString(
		_T("(Flags:%s%s) %04d/%02d/%02d %02d:%02d:%02d.%03d %10I64dBytes (Attr:%s) (Run:%5d)"),
		(detectModified_ ? _T("*") : _T("_")),
		(deletePending_ ? _T("$") : _T("_")),
		systime.wYear,
		systime.wMonth,
		systime.wDay,
		systime.wHour,
		systime.wMinute,
		systime.wSecond,
		systime.wMilliseconds,
		(__int64) size_,
		szAttributes,
		runCount_
		);
}

/*!
 * WIN32_FIND_DATAのファイルサイズから64ビット符号なし整数を取得します。
 * \param v_finddata 検索結果情報
 * \return ファイルサイズ(64ビット)
 */
unsigned __int64 CFileInfo::GetFileSize(const WIN32_FIND_DATA& v_finddata)
{
	unsigned __int64 siz =
		((unsigned __int64) v_finddata.nFileSizeHigh << 32) |
		((unsigned __int64) v_finddata.nFileSizeLow & 0xffffffff);
	return siz;
}


bool CFileInfo::update(const WIN32_FIND_DATA& v_finddata)
{
	bool modified = false;

	if (modified || name_ != v_finddata.cFileName) {
		name_  = v_finddata.cFileName;
		modified = true;
	}

	if (modified || CompareFileTime(&writetime_, &v_finddata.ftLastWriteTime) != 0) {
		writetime_ = v_finddata.ftLastWriteTime;
		modified = true;
	}

	unsigned __int64 siz = GetFileSize(v_finddata);

	if (modified || size_ != siz) {
		size_ = siz;
		modified = true;
	}

	if (modified || attributes_ != v_finddata.dwFileAttributes) {
		attributes_ = v_finddata.dwFileAttributes;
		modified = true;
	}

	return modified;
}

void CFileInfo::setExist(bool v_exist)
{
	bExist_ = v_exist;
}

void CFileInfo::setDeletePending(bool v_deletePending) 
{
	deletePending_ = v_deletePending;
}

void CFileInfo::setDeletePendingBegin(const FILETIME &ftNow)
{
	deletePendingBegin_ = ftNow;
}

void CFileInfo::setDetectModified(bool v_detectModified)
{
	detectModified_ = v_detectModified;
}

void CFileInfo::setFileName(const tstring& v_fileName)
{
	name_ = v_fileName;
}

void CFileInfo::setLastModified(const FILETIME& v_filetime)
{
	writetime_ = v_filetime;
}

void CFileInfo::setDetectBegin(const FILETIME &ftNow)
{
	detectBegin_ = ftNow;
}

void CFileInfo::setSize(unsigned __int64 v_size)
{
	size_ = v_size;
}

void CFileInfo::setAttributes(DWORD attributes)
{
	attributes_ = attributes;
}

void CFileInfo::incrementRunCount()
{
	runCount_++;
}

void CFileInfo::setRunCount(DWORD v_runCount)
{
	runCount_ = v_runCount;
}

