/*
 * libptouch.h — public C API
 *
 * Author: knb
 * Email: knb@artif.org
 */

/**
 * libptouch — Brother P-touch ラスター印刷 (USB) 用 C API
 *
 * 対象例: PT-P900W（ラスターコマンド）。実装は src/libptouch.c を参照。
 */

#ifndef LIBPTOUCH_H
#define LIBPTOUCH_H

#include "libptouch_version.h"

#include <stddef.h>
#include <stdint.h>
#include <stdio.h>

#ifdef __cplusplus
extern "C" {
#endif

/** 不透明コンテキスト（接続状態・最終エラー文字列を保持） */
typedef struct libptouch_ctx libptouch_ctx;

typedef enum {
	LIBPTOUCH_OK = 0,
	LIBPTOUCH_ERR_NOMEM = 1,
	LIBPTOUCH_ERR_ARG = 2,
	LIBPTOUCH_ERR_USB = 3,
	LIBPTOUCH_ERR_IO = 4,
	LIBPTOUCH_ERR_UNSUPPORTED = 5,
	LIBPTOUCH_ERR_NOT_FOUND = 6,
	LIBPTOUCH_ERR_IMAGE = 7,
} libptouch_err_t;

/** lsusb 例: PT-P900W — Brother Industries, Ltd (04f9:2085) */
#define LIBPTOUCH_USB_VID_BROTHER 0x04f9u
#define LIBPTOUCH_USB_PID_PTP900W 0x2085u

libptouch_ctx *libptouch_create(void);
void libptouch_destroy(libptouch_ctx *ctx);

/** 人が読める英語メッセージ（スレッド非安全: ctx ごと） */
const char *libptouch_strerror(const libptouch_ctx *ctx);
libptouch_err_t libptouch_last_error(const libptouch_ctx *ctx);

/**
 * USB でプリンタを開く（VID/PID で先頭の一致デバイスを開く。libusb のみ）。
 */
libptouch_err_t libptouch_open_usb_vid_pid(libptouch_ctx *ctx, uint16_t vid,
					   uint16_t pid);

/**
 * 既定機種（@ref LIBPTOUCH_USB_VID_BROTHER / @ref LIBPTOUCH_USB_PID_PTP900W）を開く。
 * 別機種は @ref libptouch_open_usb_vid_pid に機種ごとの VID/PID を渡す。
 */
libptouch_err_t libptouch_open_usb(libptouch_ctx *ctx);

void libptouch_close(libptouch_ctx *ctx);

typedef struct {
	uint32_t width_dots;  /**< ラスター幅（ドット） */
	uint32_t height_dots; /**< ラスター高さ（ドット・走査方向は実装と機種に依存） */
	uint8_t margin_mm;    /**< 余白など（機種・仕様に合わせて使用） */
} libptouch_raster_params_t;

/**
 * バッファサイズとパラメータの整合性のみ検査（USB 不要）。--dry-run 用。
 */
libptouch_err_t libptouch_check_raster(libptouch_ctx *ctx,
				     const uint8_t *data, size_t data_len,
				     const libptouch_raster_params_t *params);

/**
 * 1 ビット packed ラスターを USB で印刷（cv_ptp900_jpn_raster_102.pdf 準拠）。
 * 印字前にステータスでテープ幅を読み、印刷可能ドット内に画像を中央配置する。
 * width_dots は装着テープの印刷可能幅以下であること。360dpi 相当のドット列を想定。
 * @param margin_mm 余白（フィード）量。0 のとき PDF の最小 1mm（14 ドット）相当を送る。
 * 印刷時は内部でドット列を転置する（テープ幅方向とバッファの縦横の対応）。
 * @param data 1 行あたり width_dots ビットを ceil(width_dots/8) バイトで並べた連続領域
 * @param data_len 期待値: height * row_bytes, row_bytes = (width_dots + 7) / 8
 */
libptouch_err_t libptouch_print_raster(libptouch_ctx *ctx,
				       const uint8_t *data, size_t data_len,
				       const libptouch_raster_params_t *params);

/** 二値化の既定しきい値（輝度 0–255、これ未満を黒ドット） */
#define LIBPTOUCH_PNG_DEFAULT_THRESHOLD 128u

typedef struct {
	uint8_t threshold; /**< 輝度がこれ未満なら黒（1）、以上なら白（0） */
} libptouch_png_options_t;

/**
 * PNG ファイルを読み、1bit packed ラスターに変換する（libpng）。
 * @param out_raster malloc 済みバッファのポインタを返す。不要時は @ref libptouch_free_raster で解放。
 */
libptouch_err_t libptouch_png_file_to_raster(libptouch_ctx *ctx, const char *path,
					     const libptouch_png_options_t *options,
					     uint8_t **out_raster, size_t *out_raster_bytes,
					     libptouch_raster_params_t *out_params);

void libptouch_free_raster(uint8_t *raster);

/** ステータス情報リクエスト（ESC i S）の応答バイト数（cv_ptp900_jpn_raster_102.pdf） */
#define LIBPTOUCH_STATUS_LENGTH 32u

/**
 * プリンタからステータスを読む（USB オープン済みであること）。
 * 送信: 初期化 ESC @ のあと ESC i S。応答は @ref LIBPTOUCH_STATUS_LENGTH バイト固定。
 */
libptouch_err_t libptouch_get_status(libptouch_ctx *ctx,
				     uint8_t *status /* length @ref LIBPTOUCH_STATUS_LENGTH */);

/** ステータス 32 バイトを人が読める形で出力（テープ幅・種類・色など） */
void libptouch_status_fprint(FILE *fp,
			     const uint8_t *status /* length @ref LIBPTOUCH_STATUS_LENGTH */);

#ifdef __cplusplus
}
#endif

#endif /* LIBPTOUCH_H */
