#ifndef STEPLOGGER_H
#define STEPLOGGER_H

#include <string>
#include <vector>
#include <sys/stat.h>
#include <iomanip>
#include <time.h>

#include <Indoor/data/Timestamp.h>
#include "Scaler.h"
#include "Config.h"
#include "IPINHelper.h"

class StepLogger {

private:

	EvalConfig cfg;
	std::string configFile;
	std::string competitorID = "navindoor";


	std::ofstream outButtons;
	std::ofstream outPositions;

	/** all step-logger wayponts defined within the config file */
	std::vector<std::string> waypoints;
	int curWP = 0;


public:

	/** ctor with the map<->world scaler */
	StepLogger() {
		loadConfig();
		start();
	}

public:

	/** log current timestamp + waypoint and proceed with the next one */
	void onButtonPress() {

		// sanity check
		if (isDone()) {throw "all waypoints were processed";}

		// construct output string
		std::stringstream ss;
		std::string wpEntry = waypoints[curWP]; ++curWP;
		wpEntry = replace(wpEntry, ":" , " : ");
		ss << Timestamp::fromUnixTime().ms() << " : " << wpEntry << "\r\n";

		// log
		std::cout << ss.str() << std::flush;
		outButtons << ss.str(); outButtons.flush();


	}

	/** all waypoints done? */
	bool isDone() const {
		return curWP >= (int)waypoints.size();
	}


	/** log our map-relative format */
	void onNewEstimation(const double lat, const double lon, const double floorNr) {

		// construct output string
		std::stringstream ss;
		ss << Timestamp::fromUnixTime().ms() << " : " << lat << " : " << lon << " : " << floorNr << "\r\n";

		// log
		std::cout << ss.str() << std::endl;
		outPositions << ss.str(); outPositions.flush();

	}

	/** get the current waypoint's number, starting at 0 */
	int getCurrentWaypointNumber() const {
		return curWP;
	}

private:

	/** split the given string */
	std::vector<std::string> split(const std::string& str, const char delim) {
		std::vector<std::string> res;
		int start = 0;
		while (true) {
			size_t pos = str.find(delim, start);
			if (pos == std::string::npos) {break;}
			const std::string sub = str.substr(start, pos-start);
			res.push_back(sub);
			start = pos + 1;
		}
		return res;
	}

	/** string replacement helper */
	std::string replace(std::string str, const std::string& from, const std::string& to) {
		size_t start_pos = 0;
		while((start_pos = str.find(from, start_pos)) != std::string::npos) {
			str.replace(start_pos, from.length(), to);
			start_pos += to.length();
		}
		return str;
	}

	/** get the current time as [YYYYMMDD]T[HHMMSS] */
	std::string getDate() const {
		const char* format = "%Y%m%dT%H%m%S";
		std::time_t t = std::time(nullptr);
		struct tm* tt = std::localtime(&t);

		char buf[128];
		strftime(buf, 128, format, tt);
		return std::string(buf);

//		std::stringstream ss;
//		ss << std::put_time(tt, format);
//		return ss.str();
	}


private:

	/** load the config.ini and parse the waypoints */
	void loadConfig() {
		cfg.load(IPINHelper::getDataFolder() + "it.cnr.isti.steplogger.config.ini");
		const std::string tmp = cfg.get("counter");
		waypoints = split(tmp, ',');
	}

	/** create the data-folder, open the two output files and perform sanity checks */
	void start() {

		// get the output data folder and construct filenames
		const std::string folder = getOutputFolder();
		const std::string fBtn = folder + "buttonsPressed.log";
		const std::string fPos = folder + "positions.log";

		// open two output files
		outButtons.open(fBtn);		if (!outButtons.good())		{throw "error while creating file";}
		outPositions.open(fPos);	if (!outPositions.good())	{throw "error while creating file";}

		// reset current WayPoint
		curWP = 0;

	}


	/** get a DateTime dependent data folder */
	std::string getOutputFolder() {
		const std::string& folder = IPINHelper::getDataFolder();
		const std::string date = getDate();
		const std::string sub = folder + date + "_" + competitorID + "/";
		mkdir(sub.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
		return sub;
	}





	//	// config file
	//	Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) +
	//				File.separator +
	//				"it.cnr.isti.steplogger.config.ini";

	//	buttonsPressed.log
	//	milliseconds " : " number-starting-at-1" : "???" : "???" : "floor?		// see configFile config.ini
	//				java current time millis
	//	positions.log
	//	timestamp " " x " " y " " z

	//		storage/sdcard0/Download/it.cnr.isti.steplogger/

	//		Within the folder it.cnr.isti.steplogger/ StepLogger creates a folder for every measurement session, the logs are placed in folder whose name follows this convention:

	//		[YearMonthDay]T[HourMinutesSeconds][Competitor ID]
	//		 // Coordinates will need to be in the WGS84 coordinate system (longitude and latitude) for x, y,
	//		 //and the number of floor (an integer starting from 0) for z.

};

#endif // STEPLOGGER_H
