#pragma once

#include <vector>
#include <string>
#include <fstream>

#include "../util/string_util.h"



namespace util
{


// 文字列読み込み(主にファイルから)のユーティリティ
class TextReader
{
public:
	// 1行を1文字列として読み込む
	static bool LoadAsLineAry(const char* filename, std::vector<std::string>& ary);
	static bool LoadAsLineAry(std::ifstream& is, std::vector<std::string>& ary);

	// 1ファイルを1文字列として読み込む
	static bool LoadAsString(const char* filename, std::string& str);
	static bool LoadAsString(std::ifstream& is, std::string& str);

	// csvファイルを読み込む
	static bool LoadCsv(const char* filename, std::vector<std::vector< std::string > >& ary, const char separator=',');
	static bool LoadCsv(std::ifstream& is, std::vector<std::vector< std::string > >& ary, const char separator=',');
};



// ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

//! 1行を1文字列として読み込む
inline bool TextReader::LoadAsLineAry(const char* filename, std::vector<std::string>& ary)
{
	ary.clear();

	std::ifstream ifs(filename);
	if( !ifs.is_open() )
		return false;

	return LoadAsLineAry( ifs , ary );
}

//! 1行を1文字列として読み込む
inline bool TextReader::LoadAsLineAry(std::ifstream& is, std::vector<std::string>& ary)
{
	ary.clear();

	while( !is.eof() )
	{
		ary.push_back( std::string() );
		std::getline( is , ary.back() );
	}

	return true;
}

//! 1ファイルを1文字列として読み込む
inline bool TextReader::LoadAsString(const char* filename, std::string& str)
{
	str.clear();

	std::ifstream ifs(filename);
	if( !ifs.is_open() )
		return false;

	return LoadAsString( ifs , str );
}

//! 1ファイルを1文字列として読み込む
inline bool TextReader::LoadAsString(std::ifstream& is, std::string& str)
{
	str.clear();

	is.seekg( 0 , std::ios::end );
	std::fstream::pos_type pos_end = is.tellg();

	is.seekg( 0 , std::ios::beg );
	std::fstream::pos_type pos_beg = is.tellg();

	size_t stream_size = pos_end - pos_beg;
	if( stream_size == 0 )
		return true;

	str.resize( stream_size );
	is.read( &str.at(0) , (std::streamsize)stream_size );

	return true;
}


//! csvファイルを読み込む
inline bool TextReader::LoadCsv(const char* filename, std::vector<std::vector< std::string > >& ary, const char separator)
{
	ary.clear();

	std::ifstream ifs(filename);
	if( !ifs.is_open() )
		return false;

	return LoadCsv( ifs , ary , separator );
}

//! csvファイルを読み込む
inline bool TextReader::LoadCsv(std::ifstream& is, std::vector<std::vector< std::string > >& ary, const char separator)
{
	ary.clear();

	while( !is.eof() )
	{
		ary.resize( ary.size()+1 );
		std::vector<std::string>& line = ary.back();

		std::string s;
		std::getline( is , s );

		std::string::iterator iter = s.begin();
		while( iter != s.end() )
		{
			std::string::iterator next = std::find( iter , s.end() , separator );

			line.push_back( std::string( iter , next ) );
			util::String::Trim( line.back() );

			if( next == s.end() )
				break;

			iter = next;
			++iter;
		}
	}

	return true;
}


}
