/*
 * libptouch — raster right blank trim
 *
 * Author: knb
 * Email: knb@artif.org
 */

#include "libptouch_internal.h"

#include <stdlib.h>
#include <string.h>

libptouch_err_t libptouch_trim_right_blank_columns(
	libptouch_ctx *ctx, const uint8_t *data, size_t data_len,
	const libptouch_raster_params_t *in_params, uint16_t right_padding_dots,
	uint8_t **out_raster, size_t *out_raster_bytes,
	libptouch_raster_params_t *out_params)
{
	if (!ctx || !data || !in_params || !out_raster || !out_raster_bytes ||
	    !out_params) {
		if (ctx)
			ptouch_set_error(ctx, LIBPTOUCH_ERR_ARG, "null argument");
		return LIBPTOUCH_ERR_ARG;
	}

	libptouch_err_t v = libptouch_check_raster(ctx, data, data_len, in_params);
	if (v != LIBPTOUCH_OK)
		return v;

	uint32_t width = in_params->width_dots;
	uint32_t height = in_params->height_dots;
	size_t row_bytes = ((size_t)width + 7u) / 8u;
	int32_t rightmost = -1;

	for (uint32_t y = 0; y < height; y++) {
		const uint8_t *row = data + (size_t)y * row_bytes;
		for (int32_t x = (int32_t)width - 1; x >= 0; x--) {
			uint8_t b = row[(size_t)x / 8u];
			uint8_t bit = (uint8_t)(7u - ((uint32_t)x % 8u));
			if (((b >> bit) & 1u) == 0)
				continue;
			if (x > rightmost)
				rightmost = x;
			break;
		}
	}

	uint32_t new_width = width;
	if (rightmost >= 0) {
		uint32_t trimmed = (uint32_t)(rightmost + 1);
		uint32_t padded = trimmed + (uint32_t)right_padding_dots;
		if (padded > width)
			padded = width;
		if (padded < width)
			new_width = padded;
	}

	size_t new_row_bytes = ((size_t)new_width + 7u) / 8u;
	size_t total = new_row_bytes * (size_t)height;
	uint8_t *out = (uint8_t *)calloc(1u, total);
	if (!out) {
		ptouch_set_error(ctx, LIBPTOUCH_ERR_NOMEM, "calloc raster failed");
		return LIBPTOUCH_ERR_NOMEM;
	}

	uint8_t last_mask = 0xFFu;
	if ((new_width % 8u) != 0u)
		last_mask = (uint8_t)((0xFFu << (8u - (new_width % 8u))) & 0xFFu);

	for (uint32_t y = 0; y < height; y++) {
		const uint8_t *src = data + (size_t)y * row_bytes;
		uint8_t *dst = out + (size_t)y * new_row_bytes;
		memcpy(dst, src, new_row_bytes);
		dst[new_row_bytes - 1u] &= last_mask;
	}

	*out_raster = out;
	*out_raster_bytes = total;
	out_params->width_dots = new_width;
	out_params->height_dots = height;
	out_params->margin_mm = in_params->margin_mm;
	ptouch_set_error(ctx, LIBPTOUCH_OK, "");
	return LIBPTOUCH_OK;
}
