/*
** MUDoc_Embed.c
**
** Auxiliary functions for MUDoc.c
**
** Oct2020 - ABU fecit
*/

#include <string.h>
#include "xpdf_extension.h"
#include "MUDoc_Embed.h"


	// transform the coords of a fz_point, expressed in 'windows coord-sys' (fitz page space)
	//  i.e relative to the absoluteBox (i.e a /CropBox )
	// to PDF user space coord sys
static 
fz_point _PDF_point (fz_rect absBox, fz_point p) {
	p.x += absBox.x0;
	p.y = absBox.y1 - p.y ;
	return p;
}

	// transform the coords of a fz_rect, expressed in 'windows coord-sys' (fitz page space)
	//  i.e relative to the absoluteBox (i.e a /CropBox )
	// to PDF user space coord sys
static 
fz_rect _PDF_rect (fz_rect absBox, fz_rect r) {
	r.x0 += absBox.x0;
	r.x1 += absBox.x0;
	float RY0 = r.y0;   // tmp save
	r.y0 = absBox.y1 - r.y1 ;
	r.y1 = absBox.y1 - RY0;
	return r;
}


TclResCode mu_embed_xobj(Tcl_Interp* interp,
    fz_context* ctx,
    pdf_document* doc,
    pdf_page *toPage,   // where to embed xobj
	pdf_obj *xobj,
	fz_point toCenter, 
	fz_rect fromRect,
	double zoom,
	double angle,
	int overlay
	) {
	
	fz_var(toPage);
	fz_try( ctx ) {
		 // toCenter and fromRect are expressed in windows coord sys (fitz coord sys).
		 // relative to the page's visible area (cropbox)
		 // Therefore, convert them in absolute (PDF) user space coord sys.
		toCenter = _PDF_point(xpdf_page_cropbox(ctx, toPage), toCenter);
		fromRect = _PDF_rect(pdf_xobject_bbox(ctx, xobj), fromRect);
		
		fz_point srcC = xfz_rect_center(fromRect);
		
		fz_matrix mtx;
		 // A) do a scale/rotate tranforms around point srcC
		mtx = fz_translate(-srcC.x, -srcC.y);
		mtx = fz_concat( mtx, fz_scale( zoom, zoom ));
		mtx = fz_concat( mtx, fz_rotate(angle)) ;
		 // collimate srcC to dstC
		mtx = fz_concat( mtx , fz_translate(toCenter.x,toCenter.y) );
		
		xpdf_xobject_embed(ctx, doc, toPage, xobj, mtx, fromRect, overlay);
		
		 // patch
	} fz_catch( ctx ) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(fz_caught_message(ctx),-1));
		return TCL_ERROR;  	
	}
	return TCL_OK;
}


  // Parse the optional parameters of the embedPage cmd.
  // Store values in struct embedParam.
  // On error return TCL_ERROR ; an error message is left in the interpreter's result
int _parseEmbedPageOptions( Tcl_Interp *interp, int objc, Tcl_Obj* const objv[], struct embedParams *param ) {
	int argIdx = 0;
	while (argIdx < objc) {
		char *arg = Tcl_GetString(objv[argIdx++]);
		
		if ( argIdx >= objc ) {
			Tcl_SetObjResult(interp, Tcl_ObjPrintf( "option \"%s\" requires a value", arg));
			return TCL_ERROR;
		}
		
		// ? -crop
		if( strcmp(arg,"-crop") == 0 ) {
			// The fz_rect is an array of 4 floats
			if( xTcl_Get_N_Floats_FromObj( interp, objv[argIdx], 4, (float*)&(param->crop) ) != TCL_OK ) {
				return TCL_ERROR;
			}
			// result's analysis will be performed later ..
			
		// ? -to
		} else if (strcmp(arg,"-to") == 0 ) {
			// The fz_point is an array of 2 floats
			if( xTcl_Get_N_Floats_FromObj( interp, objv[argIdx], 2, (float*)&(param->to) ) != TCL_OK ) {
				return TCL_ERROR;
			}
			param->has_to = 1;
			// result's analysis will be performed later ..
			
		// -scale
		} else if (strcmp(arg,"-scale") == 0 ) {
			double doubleVal;
			if ( Tcl_GetDoubleFromObj(NULL, objv[argIdx], &doubleVal) != TCL_OK  ||  doubleVal < 1E-6 ) {
				Tcl_SetObjResult(interp, Tcl_ObjPrintf( "option \"%s\" requires a positive value greater than 0.000001", arg));
				return TCL_ERROR;
			}
			param->zoom = doubleVal;
			
		// -rotate
		} else if (strcmp(arg,"-rotate") == 0 ) {
			double doubleVal;
			if ( Tcl_GetDoubleFromObj(NULL, objv[argIdx], &doubleVal) != TCL_OK ) {
				Tcl_SetObjResult(interp, Tcl_ObjPrintf( "option \"%s\" requires a numeric value", arg));
				return TCL_ERROR;
			}
			param->rotate = doubleVal;
			
		// -over
		} else if (strcmp(arg,"-over") == 0 ) {
			int boolVal;
			if ( Tcl_GetBooleanFromObj(NULL, objv[argIdx], &boolVal) != TCL_OK) {
				return TCL_ERROR;
			}
			param->over = boolVal;
			
		// ? else ?
		} else {
			Tcl_SetObjResult(interp, Tcl_ObjPrintf( "unrecognized option \"%s\". Valid options are: -crop,-to,-scale,-rotate,-over", arg));
			return TCL_ERROR;
		}
		++argIdx;
	}
	return TCL_OK;
}
