// Enhanced Occlusion Layer Module for Foundry VTT

export function registerOcclusionConfig() {
	// Global Hook Registration
	function registerGlobalHooks() {
		const updateTriggers = [ // Update triggers for occlusion layer
			'canvasReady', 
			'canvasPan',
			'canvasTokensRefresh', 
			'updateToken', 
			'controlToken', 
			'refreshToken',
			'preUpdateScene',
			'updateScene'
		];

		updateTriggers.forEach(hookName => {
			Hooks.on(hookName, () => {
				updateOcclusionLayer(); //debouncedUpdate();
			});
		});
	}

	// Initial layer setup
	Hooks.once('ready', () => {
		if (canvas.ready)
			initializeOcclusionLayer();
	});

	// Initialize on canvas setup
	Hooks.on('canvasInit', () => {
		initializeOcclusionLayer();
	});

	// Reset on scene change
	Hooks.on('changeScene', () => {
		if (occlusionConfig.container) {
			canvas.stage.removeChild(occlusionConfig.container);
			occlusionConfig.container.destroy({ children: true });
			occlusionConfig.container = null;
			occlusionConfig.tokensLayer = null;
			occlusionConfig.initialized = false;
		}
	});
	
	// Start the module
	registerGlobalHooks();
}






// Persistent occlusion layer configuration
const occlusionConfig = {
	container: null,
	tokensLayer: null,
	initialized: false
};

// Initialize or reset the occlusion layer
function initializeOcclusionLayer() {
	// Remove existing container if it exists
	if (occlusionConfig.container) {
		canvas.stage.removeChild(occlusionConfig.container);
		occlusionConfig.container.destroy({ children: true });
	}

	// Create the main occlusion container
	occlusionConfig.container = new PIXI.Container();
	occlusionConfig.container.name = "OcclusionContainer";
	occlusionConfig.container.eventMode = 'passive';

	// Create a layer for occlusion tokens
	occlusionConfig.tokensLayer = new PIXI.Container();
	occlusionConfig.tokensLayer.name = "OcclusionTokens";
	occlusionConfig.tokensLayer.sortableChildren = true;

	// Add the layer to the container
	occlusionConfig.container.addChild(occlusionConfig.tokensLayer);

	// Add to canvas stage
	canvas.stage.addChild(occlusionConfig.container);
	canvas.stage.sortChildren();

	occlusionConfig.initialized = true;
}



function checkTokenTileIntersection(token, tile) {
	const tokenBounds = token.mesh.getBounds();
	const tileBounds = tile.mesh.getBounds();
	
	const intersection = {
		x: Math.max(tokenBounds.x, tileBounds.x),
		y: Math.max(tokenBounds.y, tileBounds.y),
		width: Math.min(tokenBounds.x + tokenBounds.width, tileBounds.x + tileBounds.width) - Math.max(tokenBounds.x, tileBounds.x),
		height: Math.min(tokenBounds.y + tokenBounds.height, tileBounds.y + tileBounds.height) - Math.max(tokenBounds.y, tileBounds.y)
	};
	
	return intersection.width > 0 && intersection.height > 0;
}

// Comprehensive update mechanism for occlusion layer
function updateOcclusionLayer() {
	// Canvas not ready, returning
	if (!canvas.ready) {
		return;
	}

	// Initializing occlusion layer
	if (!occlusionConfig.initialized) {
		initializeOcclusionLayer();
	}

	// Clear existing occlusion tokens
	occlusionConfig.tokensLayer.removeChildren();

	// Get all tokens and tiles
	const tokens = canvas.tokens.placeables;
	const tiles = canvas.tiles.placeables;
	
	tokens.forEach((token, tokenIndex) => {
		const intersectingTiles = tiles.filter(tile => checkTokenTileIntersection(token, tile));

		if (intersectingTiles.length > 0) {
			const sprite = createOcclusionSprite(token, intersectingTiles);
			if (sprite) {
				occlusionConfig.tokensLayer.addChild(sprite);
			}
		}
	});
}












// Modified createOcclusionSprite function
function createOcclusionSprite(token, intersectingTiles) {
	if (!token.mesh || !token.mesh.texture) return null;

	// Criar sprite com logs
	const sprite = new PIXI.Sprite(token.mesh.texture);
	sprite.position.set(token.mesh.position.x, token.mesh.position.y);
	sprite.anchor.set(token.mesh.anchor.x, token.mesh.anchor.y);
	sprite.angle = token.mesh.angle;
	sprite.scale.set(token.mesh.scale.x, token.mesh.scale.y);

	// Criar e configurar filtro
	const occlusionFilter = 
	
	// Aplicar filtro
	sprite.filters = [occlusionFilter, colorMatrix];
	sprite.eventMode = 'passive';

	return sprite;
}














// Código do filtro de outline customizado (adicionar depois)

// Create new outline filter
const isoOutlineFilter = new PIXI.filters.isoOutlineFilter();
isoOutlineFilter.thickness = 0.005;
isoOutlineFilter.color = 0x00ff59;

// Create a greyscale/dimming filter
const colorMatrix = new PIXI.ColorMatrixFilter();
colorMatrix.alpha = 1;
colorMatrix.matrix = [
	0.0,  0.0,  0.0,  0.0,  0.0,
	0.0,  0.0,  0.0,  0.0,  0.0,
	1.0,  1.0,  1.0,  0.0,  0.0,
	0.0,  0.0,  0.0,  1.0,  0.0
];
