/*
 * Copyright 2020-2023 MicroEJ Corp. All rights reserved.
 * This library is provided in source code for use, modification and test, subject to license terms.
 * Any modification of the source code will break MicroEJ Corp. warranties on the whole library.
 */
package ej.mwt.render;

import ej.microui.display.Display;
import ej.microui.display.GraphicsContext;
import ej.mwt.Container;
import ej.mwt.Desktop;
import ej.mwt.Widget;

/**
 * This render policy keeps the initial order of the widgets. That means that when a widget is rendered, the widgets
 * after it in the hierarchy and that have an intersection with it, are also rendered.
 * <p>
 * When a widget is asked to be rendered, all the widgets that overlap it in the desktop hierarchy are also rendered. A
 * widget is considered to overlap another one if:
 * <ul>
 * <li>their bounds intersect,</li>
 * <li>it is after the other one when browsing the hierarchy following a depth-first algorithm.</li>
 * </ul>
 */
public class OverlapRenderPolicy extends DefaultRenderPolicy {

	/**
	 * Creates an overlap render policy.
	 *
	 * @param desktop
	 *            the desktop.
	 */
	public OverlapRenderPolicy(Desktop desktop) {
		super(desktop);
	}

	@Override
	protected void renderWidget(Widget widget, int x, int y, int width, int height) {
		// reset translation and clip
		GraphicsContext g = Display.getDisplay().getGraphicsContext();
		g.resetTranslation();
		g.resetClip();

		// compute translation and clip
		setParentClip(widget, g);
		g.intersectClip(widget.getX() + x, widget.getY() + y, width, height);

		// Save clip to apply it for siblings.
		int translateX = g.getTranslationX();
		int translateY = g.getTranslationY();
		int clipX = g.getClipX();
		int clipY = g.getClipY();
		int clipWidth = g.getClipWidth();
		int clipHeight = g.getClipHeight();

		// render widget
		renderWidget(g, widget);

		renderSiblings(g, widget, translateX, translateY, clipX, clipY, clipWidth, clipHeight);
	}

	private void renderSiblings(GraphicsContext g, Widget widget, int translateX, int translateY, int clipX, int clipY,
			int clipWidth, int clipHeight) {
		Container parent = widget.getParent();
		if (parent != null) {
			// Browse the children of the parent after the index of the given widget.
			int childIndex = parent.getChildIndex(widget);
			int length = parent.getChildrenCount();
			for (int i = childIndex + 1; i < length; i++) {
				Widget child = parent.getChild(i);
				assert child != null;

				if (child.isShown()) {
					g.setTranslation(translateX, translateY);
					g.setClip(clipX, clipY, clipWidth, clipHeight);
					renderWidget(g, child);
				}
			}
			// Render the siblings of the parent.
			int parentX = parent.getX() + parent.getContentX();
			int parentY = parent.getY() + parent.getContentY();
			renderSiblings(g, parent, translateX - parentX, translateY - parentY, clipX + parentX, clipY + parentY,
					clipWidth, clipHeight);
		}
	}

}
