#include <psemek/app/resource.hpp>
#include <psemek/log/log.hpp>
#include <psemek/util/to_string.hpp>

#include <android/asset_manager_jni.h>

namespace
{

	jobject assetManagerRef;
	AAssetManager * assetManager;

	struct stream_impl
		: psemek::io::istream
	{
		stream_impl(AAsset * asset)
			: asset_(asset)
		{}

		~stream_impl()
		{
			AAsset_close(asset_);
		}

		std::size_t read(char * p, std::size_t size) override
		{
			int result = AAsset_read(asset_, p, size);
			if (result < 0)
				throw std::runtime_error("Failed to read from resource");
			return result;
		}

		bool finished() const override
		{
			return AAsset_getRemainingLength64(asset_) == 0;
		}

	private:
		AAsset * asset_;
	};

}

namespace psemek::app
{

	std::unique_ptr<io::istream> open_resource(std::filesystem::path const & relative_path)
	{
		log::info() << "Opening resource " << relative_path;

		auto asset = AAssetManager_open(assetManager, relative_path.c_str(), AASSET_MODE_STREAMING);
		if (!asset)
			throw std::runtime_error(util::to_string("Failed to open resource ", relative_path));

		return std::make_unique<stream_impl>(asset);
	}

}

extern "C" void Java_psemek_app_PsemekApplication_setAssetManager(JNIEnv * env, jclass, jobject manager)
{
	assetManagerRef = env->NewLocalRef(manager);
	assetManager = AAssetManager_fromJava(env, manager);
}
