#ifndef EX_ROLLING_FILE_APPENDER_H
#define EX_ROLLING_FILE_APPENDER_H

#include <log4cpp/RollingFileAppender.hh>
#include <log4cpp/LoggingEvent.hh>

#include <sstream>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <iomanip>
#include <memory>
#include <stdio.h>
#include <math.h>
#include <string>
#include <stdarg.h>
#include <unordered_map>

class FileData{
private:
	std::string fileName;
	std::string fileDate;
public:
	FileData(std::string fileName,std::string fileDate){
		this->fileName = fileName;
		this->fileDate = fileDate;
	}

public:
	std::string getFileName(){
		return fileName;
	}
	
	std::string getFileDate(){
		return fileDate;
	}

	void setFileName(std::string fileName){
		this->fileName = fileName;
	}

	void setFileDate(std::string fileDate){
		this->fileDate = fileDate;
	}
};


class ExRollingFileAppender : public RollingFileAppender{
public:
	ExRollingFileAppender(const std::string& name, 
		const std::string& fileName,
		size_t maxFileSize = 10*1024*1024, 
		unsigned int maxBackupIndex = 1,
		bool append = true,
		mode_t mode = 00644){
			RollingFileAppender(name,fileName,append,mode);
			_maxBackupIndex = maxBackupIndex > 0 ? maxBackupIndex : 1;
			_maxBackupIndexWidth = (_maxBackupIndex > 0) ? log10((float)_maxBackupIndex)+1 : 1;
			_maxFileSize = maxFileSize; 

			//strDate
	}

protected:
	unsigned int _maxBackupIndex;
	unsigned short int _maxBackupIndexWidth;
	size_t _maxFileSize;
private:
	std::string strDate;
	std::unordered_map<std::string,std::shared_ptr<FileData>> fileData;
public:
	void setMaxBackupIndex(unsigned int maxBackups){
		_maxBackupIndex = maxBackups; 
		_maxBackupIndexWidth = (_maxBackupIndex > 0) ? log10((float)_maxBackupIndex)+1 : 1;
	}

	unsigned int getMaxBackupIndex() const{
		return _maxBackupIndex; 
	}

	void setMaximumFileSize(size_t maxFileSize){
		_maxFileSize = maxFileSize;
	}

	size_t getMaxFileSize() const{
		return _maxFileSize;
	}

	void rollOver(){
		if (_maxBackupIndex > 0) {
			std::ostringstream filename_stream;
			filename_stream << _fileName << "." << std::setw( _maxBackupIndexWidth ) << std::setfill( '0' ) << _maxBackupIndex << std::ends;
			// remove the very last (oldest) file
			std::string last_log_filename = filename_stream.str();
			// std::cout << last_log_filename << std::endl; // removed by request on sf.net #140
			::remove(last_log_filename.c_str());

			// rename each existing file to the consequent one
			for(unsigned int i = _maxBackupIndex; i > 1; i--) {
				filename_stream.str(std::string());
				filename_stream << _fileName << '.' << std::setw( _maxBackupIndexWidth ) << std::setfill( '0' ) << i - 1 << std::ends;  // set padding so the files are listed in order
				::rename(filename_stream.str().c_str(), last_log_filename.c_str());
				last_log_filename = filename_stream.str();
			}
			// new file will be numbered 1
			::rename(_fileName.c_str(), last_log_filename.c_str());
		}
		_fd = ::open(_fileName.c_str(), _flags, _mode);
	}

	void SubAppend(const LoggingEvent& event){
		RollingFileAppender::_append(event);
		off_t offset = ::lseek(_fd, 0, SEEK_END);
		if (offset < 0) {
			// XXX we got an error, ignore for now
		} else {
			//日期超过了就重建目录和文件
			//文件超过指定大小就重新建立文件
			if(static_cast<size_t>(offset) >= _maxFileSize) {
				rollOver();
			}
		}
	}

	std::string getIndex(int i,int maxBackupIndexLength){
		std::string index = "";
		return index;
	}
};

#endif