import { Mesh } from 'three';
import { mergeBufferGeometries } from 'three/examples/jsm/utils/BufferGeometryUtils.js';

import MSDFGlyph from './MSDFGlyph.js';

/**

Job:
- Computing glyphs dimensions according to this component's font and content
- Create the text Mesh (call MSDFGlyph for each letter)

Knows:
- The Text component for which it creates Meshes
- The parameters of the text mesh it must return

 */

function getGlyphDimensions( options ) {

	const FONT = options.font;

	const FONT_SIZE = options.fontSize;

	const GLYPH = options.glyph;

	const SCALE_MULT = FONT_SIZE / FONT.info.size;

	//

	const charOBJ = FONT.chars.find( charOBJ => charOBJ.char === GLYPH );

	let width = charOBJ ? charOBJ.width * SCALE_MULT : FONT_SIZE / 3;

	let height = charOBJ ? charOBJ.height * SCALE_MULT : 0;

	// handle exported whitespaces
	if ( width === 0 ) {

		// if this whitespaces in is the charset, use its xadvance value
		// or fallback to fontSize
		width = charOBJ ? charOBJ.xadvance * SCALE_MULT : FONT_SIZE;

	}


	if ( height === 0 ) height = FONT_SIZE * 0.7;

	if ( GLYPH === '\n' ) width = 0;

	const xadvance = charOBJ ? charOBJ.xadvance * SCALE_MULT : width;
	const xoffset = charOBJ ? charOBJ.xoffset * SCALE_MULT : 0;

	// world-space length between lowest point and the text cursor position
	const anchor = charOBJ ? ( ( charOBJ.yoffset + charOBJ.height - FONT.common.base ) * FONT_SIZE ) / FONT.common.lineHeight : 0;

	// const lineHeight = FONT.common.lineHeight * SCALE_MULT;

	// console.log( lineHeight )

	return {
		// lineHeight,
		width,
		height,
		anchor,
		xadvance,
		xoffset
	};

}


/**
 * Try to find the kerning amount of a
 * @param font
 * @param {string} glyphPair
 * @returns {number}
 */
function getGlyphPairKerning( font, glyphPair ) {

	const KERNINGS = font._kernings;
	return KERNINGS[ glyphPair ] ? KERNINGS[ glyphPair ] : 0;

}


//

/**
 * Creates a THREE.Plane geometry, with UVs carefully positioned to map a particular
 * glyph on the MSDF texture. Then creates a shaderMaterial with the MSDF shaders,
 * creates a THREE.Mesh, returns it.
 * @private
 */
function buildText() {

	const translatedGeom = [];

	this.inlines.forEach( ( inline, i ) => {

		translatedGeom[ i ] = new MSDFGlyph( inline, this.getFontFamily() );

		translatedGeom[ i ].translate( inline.offsetX, inline.offsetY, 0 );

	} );

	const mergedGeom = mergeBufferGeometries( translatedGeom );

	const mesh = new Mesh( mergedGeom, this.getFontMaterial() );

	return mesh;

}

//

export default {
	getGlyphDimensions,
	getGlyphPairKerning,
	buildText
};