/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 */

#pragma once
#include <vector>
#include <string>
#include <stdint.h>
#include <ctime>
#include <variant>

namespace OpenVulkano::Image
{
	struct RationalValue
	{
		uint32_t nominator;
		uint32_t denominator;
	};

	enum class LatitudeRef
	{
		NORTH,
		SOUTH,
	};
	enum class LongitudeRef
	{
		EAST,
		WEST,
	};
	enum class GPSTrackRef
	{
		TRUE_NORTH,
		MAGNETIC
	};

	struct GPSCoords
	{
		int32_t degrees, minutes, seconds;
		std::variant<LatitudeRef, LongitudeRef> ref;

		GPSCoords(float decimalDegrees, bool isLatitude);
		GPSCoords(int32_t degrees, int32_t minutes, int32_t seconds, LatitudeRef ref);
		GPSCoords(int32_t degrees, int32_t minutes, int32_t seconds, LongitudeRef ref);
	};

	class ExifBuilder
	{
	public:
		int orientation = 0;
		std::string make;
		std::string model;
		RationalValue xResolution = { 0, 0 };
		RationalValue yResolution = { 0, 0 };
		int resolutionUnit = 0;
		RationalValue exposureTime = { 0, 0 };
		std::string dateTaken; // format: yyyy:mm:dd hh:mm:ss
		std::string softwareUsed = "OpenVulkano";

		GPSCoords latitude = { 0, 0, 0, LatitudeRef::NORTH };
		GPSCoords longitude = { 0, 0, 0, LongitudeRef::EAST };

		bool altitudeIsAboveSeaLevel = true;
		uint32_t altitude = 0;

		GPSTrackRef trackRef = GPSTrackRef::TRUE_NORTH;
		float track = 0; // range is [0.0; 360.0)


		void SetAltitude(float level);
		void SetTime(std::time_t timestamp);
		// Typical usage is -> jpeg_write_marker(cinfo, JPEG_APP0 + 1, exif_data.data(), exif_data.size());
		[[nodiscard]] std::vector<uint8_t> Build();
		[[nodiscard]] static std::string StringFromTime(std::time_t time);
		[[nodiscard]] static std::string GetCurrentTimestamp();
	};
}