#ifndef WIFICALIBMODEL_H
#define WIFICALIBMODEL_H

#include <fstream>

#include <Indoor/sensors/radio/setup/WiFiFingerprint.h>

class WiFiCalibrationDataModel {

private:

	/** the file to save the calibration model to */
	std::string file;

	/** all fingerprints (position -> measurements) within the model */
	std::vector<WiFiFingerprint> fingerprints;

public:

	WiFiCalibrationDataModel(const std::string& file) : file(file) {
		load();
	}

	const std::vector<WiFiFingerprint>& getFingerprints() {
		return fingerprints;
	}

	/** deserialize the model */
	void load() {

		// open and check
		std::ifstream inp(file.c_str());
		if (inp.bad() || inp.eof() || ! inp.is_open()) { return; }

		// read all entries
		while (!inp.eof()) {

			// each section starts with [fingerprint]
			std::string section;
			inp >> section;
			if (inp.eof()) {break;}
			if (section != "[fingerprint]") {throw Exception("error!");}

			// deserialize it
			WiFiFingerprint wfp;
			wfp.read(inp);
			fingerprints.push_back(wfp);

		}

		inp.close();

	}


	/** serialize the model */
	void save() {

		// open and check
		std::ofstream out(file.c_str());
		if (out.bad()) {throw Exception("error while opening " + file + " for write");}

		// write all entries
		for (const WiFiFingerprint& wfp : fingerprints) {
			out << "[fingerprint]\n";
			wfp.write(out);
		}

		// done
		out.close();

	}

	/** get the fingerprint for the given location. if no fingerprint exists, an empty one is created! */
	WiFiFingerprint& getFingerprint(const Point3 pos_m) {

		// try to find an existing one
		for (WiFiFingerprint& wfp : fingerprints) {
			// get within range of floating-point rounding issues
			if (wfp.pos_m.getDistance(pos_m) < 0.001) {return wfp;}
		}

		// create a new one and return its reference
		WiFiFingerprint wfp(pos_m);
		fingerprints.push_back(wfp);
		return fingerprints.back();

	}

};

#endif // WIFICALIBMODEL_H
