#include "heat.h"
#include "cache.h"

#include <heatmap.h>
#include <colorschemes/Spectral.h>
#include <Magick++.h>

#include <set>
#include <vector>
#include <string>
#include <assert.h>

Heat::Heat(const Map* m) : mp(m) {
	assert(mp);

#ifdef graphicsmagick
	Magick::InitializeMagick(nullptr);
#endif
}

void Heat::generate(const std::string& filename, const pCaches& points, int stamp_size, const std::string& theme) {
	heatmap_t* hm = heatmap_new(mp->size_x, mp->size_y);
	heatmap_stamp_t* stamp = heatmap_stamp_gen(stamp_size);
	std::vector<unsigned char> image(mp->size_x * mp->size_y * 4);

	for (auto el : points) {
		if (mp->contains(Position(el->pos.lat, el->pos.lon))) {
			heatmap_add_point_with_stamp(hm, mp->coordinate_x(Position(el->pos.lat, el->pos.lon)), mp->coordinate_y(Position(el->pos.lat, el->pos.lon)), stamp);
			// std::cout << mp->coordinate_x(Position(el.pos.lon, el.pos.lat)) << '\t' << mp->coordinate_y(Position(el.pos.lon, el.pos.lat)) << '\n';
		}
	}

	if (theme == "soft")
		heatmap_render_to(hm, heatmap_cs_Spectral_soft, &image[0]);
	else if (theme == "exp")
		heatmap_render_to(hm, heatmap_cs_Spectral_mixed_exp, &image[0]);
	else
		throw 0;
	heatmap_free(hm);

	Magick::Image contour(mp->map_file);
	Magick::Image heatmap(mp->size_x, mp->size_y, "RGBA", Magick::CharPixel, &image[0]);

	contour.composite(heatmap, 0, 0, Magick::OverCompositeOp);
	contour.write(filename);
	// heatmap.write("geostat_heat.png");
}

void Heat::generate_path(const std::string& filename, const Date_Caches& sorted) {
	Magick::Image contour(mp->map_file);

	contour.strokeColor("black");
	contour.strokeWidth(2);

#ifdef graphicsmagick
	std::list<Magick::Drawable> draw;
#else
	std::vector<Magick::Drawable> draw;
#endif

	const Cache* prev = sorted.begin()->second;

	float h = 1./3;
	float h_step = 2./3/(sorted.size()-1);

	for (auto el = sorted.begin()++; el != sorted.end(); el++) {
		draw.push_back(Magick::DrawableStrokeColor(Magick::ColorHSL(h, 1, 0.5)));
		h += h_step;
		draw.push_back(Magick::DrawableLine(mp->coordinate_x(Position(el->second->pos.lat, el->second->pos.lon)), mp->coordinate_y(Position(el->second->pos.lat, el->second->pos.lon)),
											mp->coordinate_x(Position(prev->pos.lat, prev->pos.lon)), mp->coordinate_y(Position(prev->pos.lat, prev->pos.lon))));
		prev = el->second;
	}
	contour.draw(draw);
	contour.write(filename);
}
