package xaero.rotatenjump.game.graphics;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.opengl.GLES20;
import android.text.TextPaint;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.HashMap;

import xaero.rotatenjump.game.graphics.model.Model;
import xaero.rotatenjump.game.graphics.model.Square;

/**
 * Created by xaero on 21/08/2017.
 */

public class FontRenderer {

    private Model fontSheetModel;
    private HashMap<Character, float[]> characterData;
    private Texture fontSheetTexture;
    private float fontHeight;
    private int size;
    private FloatBuffer customUV;

    public FontRenderer(int size, int fontSize, Typeface font){
        this.size = size;
        ByteBuffer bb = ByteBuffer.allocateDirect(32);//4 * 2 * 4
        bb.order(ByteOrder.nativeOrder());
        customUV = bb.asFloatBuffer();
        fontHeight = (float)fontSize / size;//in texture coordinates
        characterData = new HashMap<>();
        Bitmap fontSheet = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(fontSheet);
        Paint paint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
        paint.setTypeface(font);
        paint.setTextSize(fontSize);
        paint.setTextAlign(Paint.Align.LEFT);
        paint.setColor(Color.WHITE);
       // canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), paint);

        float[] temp = new float[1];
        float offset = 0;
        int line = 1;
        int lineSize = fontSize + 20;
        for(int i = 32; i < 256; i++){
            char c = (char)i;
            paint.getTextWidths(Character.toString(c), temp);
            float width = temp[0];
            if (offset + width >= size) {
                line++;
                offset = 0;
            }
            float y = line * lineSize;
            characterData.put(c, new float[]{offset / size, (y + fontSize / 4f) / size, width/size});//x, y, w (h is the same for all)
            canvas.drawText(Character.toString(c), offset, y, paint);
            offset += width + 5;
            //Log.d("test", Character.toString(c) + " " + width + " " + i);
        }
        fontSheetTexture = new Texture(fontSheet, GLES20.GL_LINEAR);
        fontSheetModel = new Square(fontSheetTexture);
    }

    public void drawGUIString(String s, float x, float y, float scale){
        drawString(s, x, y, 0, scale, 1);
    }

    public void drawCenteredGUIString(String s, float x, float y, float scale){
        drawCenteredString(s, x, y, 0, scale, 1);
    }

    public void drawString(String s, float x, float y, float z, float scale, float scaleY){
        float offset = 0;
        for(int i = 0; i < s.length(); i++) {
            float[] data = characterData.get(s.charAt(i));
            customUV.put(data[0]).put(data[1] - fontHeight);//bottom left
            customUV.put(data[0] + data[2]).put(data[1] - fontHeight);//bottom right
            customUV.put(data[0] + data[2]).put(data[1]);//top right
            customUV.put(data[0]).put(data[1]);//top left
            customUV.position(0);
            fontSheetModel.draw(x + offset + data[2] * scale * size / 2f, y, z,0, 0, 0, data[2] * scale * size, fontHeight * scale * size * scaleY, 1, customUV);
            offset += data[2] * scale * size;
            //Log.d("test", (x + offset) + " " + (y) + " " + (data[2] * scale) + " " + (fontHeight * scale));
        }
    }

    public void drawCenteredString(String s, float x, float y, float z, float scale, float scaleY){
        drawString(s, x - getStringWidth(s) / 2 * scale, y, z, scale, scaleY);
    }

    public void drawStringRightAlign(String s, float x, float y, float z, float scale, float scaleY){
        drawString(s, x - getStringWidth(s) * scale, y, z, scale, scaleY);
    }

    public float getStringWidth(String s){
        float result = 0;
        for(int i = 0; i < s.length(); i++)
            result += characterData.get(s.charAt(i))[2] * size;
        return result;
    }

    public Model getFontSheetModel() {
        return fontSheetModel;
    }

}
