/* GPC (C) 2017-2018 Stephane Charette <stephanecharette@gmail.com>
 * $Id: IJS.hpp 2456 2018-02-26 06:36:51Z stephane $
 */

#pragma once

#include "GPC.hpp"


class IJB final
{
	public:

		#pragma pack(push, 1)

		/** Structure that represents the IBJ bimaps.  There is a 94-byte
		 * header prior to the actual image data.  The length at offset 0x5a
		 * should be the same as the file size minus the 94-byte header, and
		 * the image data begins immediately after lenght.
		 */
		struct RecIJB
		{
			uint32_t	unknown1;			///< 0x00 - 0x03:  seems to always be 0x01
			char		short_name[14];		///< 0x04 - 0x11:  "J01_000.bmp"; enough room to store full 8.3 + NULL
			char		long_filename[64];	///< 0x12 - 0x51:  "J01_000_{9D284FFa-0FC3-4B47-9B8D-6651BDF5657E}" ...length unknown, 64 is just a guess @warning This is just the filename without the file extension!
			uint32_t	width;				///< 0x52 - 0x55:  width of image in bytes, rounded up (meaning a 150px wide image shows up as @p "20", since 20 bytes * 8 bits = 160px)
			uint32_t	height;				///< 0x56 - 0x59:  height of image in bytes, rounded up
			uint32_t	len;				///< 0x5a - 0x5d:  number of data bytes in image (starting at 0x5e)
			uint8_t		data[0];			///< 0x5e - ....:  raw pixel image data, 1 bit per pixel
		};

		#pragma pack(pop)

		/// Empty constructor.  @see @ref load()
		IJB(void);

		/// Destructor.
		~IJB(void);

		IJB(const IJB &rhs);

		IJB &operator=(const IJB &rhs);

		/// Load the given .ijb file.
		IJB &load(const File &filename);

		/// Summarize the .ijb as a text message for the user.
		std::string summary(void) const;

		/** Extract the image data from @ref contents, and re-build a new
		 * user-viewable image.  Instead of calling this directly, see the
		 * image stored as @ref img.
		 */
		Image extract_image() const;

		IJB &set_new_image(const Image &new_image);

		IJB &rotate_image_180(void);

		/** Create a @p PNG file in the same directory as the IJB, and name
		 * it so it is obvious which image corresponds with each @p .ijb.
		 * @param force Images are only written if they don't already on disk,
		 * unless @p true is passed in which forces the image to be re-written.
		 */
		const IJB &create_browseable_image(const bool force=false) const;

		/// The entire contents of the file is loaded into this vector.
		VBytes contents;

		/// Pointer to the bitmap record.  Should point to @p nullptr or the first byte of @ref contents.
		const RecIJB *rec;

		/// .ijb file.
		File file;

		/** The image file extracted, rotated, and flipped from the .ijb file.
		 * This is automatically done by @ref extract_image() when the .ibj
		 * file is first loaded in @ref load().
		 */
		Image img;
};
