package electrosphere.renderer.ui.elements;

import org.joml.Vector3f;
import org.lwjgl.util.yoga.Yoga;

import electrosphere.engine.Globals;
import electrosphere.renderer.OpenGLState;
import electrosphere.renderer.RenderPipelineState;
import electrosphere.renderer.debug.DebugRendering;
import electrosphere.renderer.ui.elementtypes.DrawableElement;
import electrosphere.renderer.ui.elementtypes.Element;
import electrosphere.renderer.ui.events.Event;
import electrosphere.renderer.ui.font.Font;

/**
 * A label
 */
public class Label extends StandardContainerElement implements DrawableElement {
    
    /**
     * The default font size
     */
    public static final float DEFAULT_FONT_SIZE = 1.0f;

    public boolean visible = false;


    String text = "";
    int textPixelWidth = 0;
    
    float fontSize = 1.0f;
    
    static final Vector3f windowDrawDebugColor = new Vector3f(1.0f,1.0f,1.0f);

    Font font;

    /**
     * Creates a label element
     * @param text the text for the label
     * @return the label element
     */
    public static Label createLabel(String text){
        Label rVal = new Label(1.0f);
        rVal.setText(text);
        return rVal;
    }

    /**
     * Simplified constructor
     * @param fontSize the size of the font (default is 1.0f)
     */
    public Label(float fontSize){
        super();
        this.font = Globals.fontManager.getFont("default");
        setHeight((int)(font.getFontHeight() * fontSize));
        this.fontSize = fontSize;
        Yoga.YGNodeStyleSetFlexDirection(this.yogaNode, Yoga.YGFlexDirectionRow);
    }
    
    /**
     * Creates a label with absolute positioning
     * @param x the x position
     * @param y the y position
     * @param fontSize the font size (default is 1.0f)
     */
    public Label(int x, int y, float fontSize){
        super();
        this.setPositionX(x);
        this.setPositionY(y);
        this.font = Globals.fontManager.getFont("default");
        setHeight((int)(font.getFontHeight() * fontSize));
        this.fontSize = fontSize;
        Yoga.YGNodeStyleSetFlexDirection(this.yogaNode, Yoga.YGFlexDirectionRow);
    }
    
    void generateLetters(){
        //free children
        for(Element child : childList){
            Yoga.YGNodeFree(child.getYogaNode());
        }
        childList.clear();
        int accumulatingWidth = 0;
        for(int i = 0; i < text.length(); i++){
            char toDraw = text.charAt(i);
            Vector3f bitMapDimension = this.font.getDimensionOfCharacterDiscrete(toDraw);
            BitmapCharacter newLetter = new BitmapCharacter(this.font,(int)(bitMapDimension.x * fontSize), this.height, toDraw);
            accumulatingWidth += bitMapDimension.x * fontSize;
            childList.add(newLetter);
            Yoga.YGNodeInsertChild(yogaNode, newLetter.getYogaNode(), childList.size() - 1);
        }
        Yoga.YGNodeStyleSetWidth(yogaNode, accumulatingWidth);
    }
    
    public void setText(String text){
        this.text = text;
        textPixelWidth = 0;
        for(int i = 0; i < text.length(); i++){
            Vector3f bitMapDimension = this.font.getDimensionOfCharacterDiscrete(text.charAt(i));
            textPixelWidth = textPixelWidth + (int)bitMapDimension.x;
        }
        generateLetters();
    }

    public void setColor(Vector3f color){
        for(Element character : childList){
            ((BitmapCharacter)character).setColor(color);
        }
    }
    
    public String getText(){
        return text;
    }

    @Override
    public void draw(
        RenderPipelineState renderPipelineState,
        OpenGLState openGLState,
        int parentFramebufferPointer,
        int parentPosX,
        int parentPosY,
        int parentWidth,
        int parentHeight
    ) {
        for(Element child : childList){
            ((DrawableElement)child).draw(
                renderPipelineState,
                openGLState,
                parentFramebufferPointer,
                parentPosX + this.internalPositionX,
                parentPosY + this.internalPositionY,
                parentWidth,
                parentHeight
            );
        }

        if(Globals.RENDER_FLAG_RENDER_UI_BOUNDS && DebugRendering.RENDER_DEBUG_OUTLINE_LABEL){
            float ndcX =      (float)(internalPositionX)/parentWidth;
            float ndcY =      (float)(internalPositionY)/parentHeight;
            float ndcWidth =  (float)internalWidth/parentWidth;
            float ndcHeight = (float)internalHeight/parentHeight;
            Vector3f boxPosition = new Vector3f(ndcX,ndcY,0);
            Vector3f boxDimensions = new Vector3f(ndcWidth,ndcHeight,0);
            DebugRendering.drawUIBounds(parentFramebufferPointer, boxPosition, boxDimensions, windowDrawDebugColor);
        }
    }

    public boolean getVisible() {
        return visible;
    }

    public void setVisible(boolean draw) {
        this.visible = draw;
    }
    
    public boolean handleEvent(Event event){
        return true;
    }
    
}
