#include "ofApp.h"
#include "conversion.h"
#include "import-font.h"
#include "ofAppRunner.h"
#include "ofGraphics.h"
#include "ofGraphicsBaseTypes.h"
#include "ofUtils.h"

//--------------------------------------------------------------
void ofApp::setup(){
    ofSetFrameRate(30);
    ofSetVerticalSync(false);
    //string fontName = "RobotoFlex.ttf";
    //string fontPath = "data/fonts/" + fontName;
    string fontPath = "data/celines-fonts/testing2VF.ttf";
    //string fontPath = "data/celines-fonts/Cottagecore.ttf";
    ofxMsdfgen::AtlasSettings settings;
    settings.characters = "ABCDEFGHIJKL";
    atlas.setup(fontPath, settings);
    atlasImage = atlas.getAtlasImage();
    glyphGeometries = atlas.getGlyphGeometries();
    #ifdef TARGET_EMSCRIPTEN
        shader.load("ofxMsdfgen/shaders/unitRange/ES3/shader");
    #else
        shader.load("ofxMsdfgen/shaders/unitRange/GL3/shader");
    #endif

    cam.setPosition(ofGetWidth() / 2, ofGetHeight() / 2, -1000);
    cam.lookAt(glm::vec3(ofGetWidth() / 2, ofGetHeight() / 2, 0));
}

//--------------------------------------------------------------
void ofApp::update(){

}

//--------------------------------------------------------------
void ofApp::draw(){
    ofBackground(ofColor::lightBlue);
    cam.begin();
    ofEnableDepthTest();
    ofEnableAlphaBlending();
    ofPushMatrix();
    ofTranslate(
        ofMap(sin(ofGetElapsedTimeMillis() * 0.0001), -1, 1, 0, ofGetWidth() - atlasImage.getWidth()),
        ofMap(cos(ofGetElapsedTimeMillis() * 0.0001), -1, 1, 0, ofGetHeight() - atlasImage.getHeight()),
        0);
    atlasImage.draw(0, 0);
    ofPopMatrix();

    shader.begin();
    shader.setUniformTexture("msdf", atlasImage.getTexture(), 0);
    shader.setUniform4f("fontColor", ofFloatColor::white);

    ofPushMatrix();
    ofTranslate(40, 40, 0);
    //ofScale(4, 4, 4);
    string word = "";
    float tx = 0;
    float ty = 0;
    //for(int c = 0; c < word.length(); c++){
    //unicode_t character = word[c];
    //const ofxMsdfgen::GlyphGeometry & glyphGeometry = glyphGeometries[0];
    int amount = 0;
    float mouser = ofGetMousePressed() ? ofMap(ofGetMouseX(), 0, ofGetWidth(), 0.001, 1) : 1;
    for(int iz = 0; iz < 3; iz++){
        tx = 0;
        ty = 0;
        for(int i = 0; i < 42; i++){
            for(const auto & glyphGeometry : glyphGeometries){
                word += glyphGeometry.getCodepoint();
                int x, y, w, h;
                glyphGeometry.getBoxRect(x, y, w, h);
                glm::vec2 unitRange = glm::vec2(atlas.settings.pixelRange) / glm::vec2(w, h);
                shader.setUniform2f("unitRange", unitRange * mouser);
                if(tx + w > ofGetWidth()){
                    ty += atlas.settings.scale * 2;
                    tx = 0;
                }
                ofPushMatrix();
                ofTranslate(tx, ty, 0);
                atlasImage.drawSubsection(0, 0, w, h, x, y, w, h);
                ofPopMatrix();
                tx += atlas.settings.scale;
                amount++;
            }
        }
        ofTranslate(0, 0, 100);
    }
    ofPopMatrix();
    ofDisableAlphaBlending();
    ofDisableDepthTest();
    cam.end();

    shader.end();
    ofPushStyle();
    ofSetColor(ofColor::purple);
    ofDrawBitmapString("glyph amount: " + ofToString(amount) + "\n"
                       + "word: " + word + "\n"
                       + "mouser: " + ofToString(mouser) + "\n"
                       + "fps: " + ofToString(ofGetFrameRate()), 20, 20);
    ofPopStyle();
}

//--------------------------------------------------------------
void ofApp::keyPressed(int key){
    if(key == 's'){
        atlasImage.save("web_atlasImage.png");
    }
}

//--------------------------------------------------------------
void ofApp::keyReleased(int key){

}

//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y){

}

//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button){

}

//--------------------------------------------------------------
void ofApp::mouseEntered(int x, int y){

}

//--------------------------------------------------------------
void ofApp::mouseExited(int x, int y){

}

//--------------------------------------------------------------
void ofApp::windowResized(int w, int h){

}

//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg){

}

//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo){

}
