//I'm too lazy to give context, if you care then just ask and I will make my engine public
void UpdateDebugUI(game_state* GameState){
    ui_data* uiData = GameState->uiData;
    
    frame_input* finput = &GameState->finput;
    vec2 mouseScreenDelta = {(float)finput->mousedx,(float)finput->mousedy};
    vec2 mouseScreenPos = {(float)finput->mousex,(float)finput->mousey};

    //setup all the info
    ui_element* window = AddUIWindow(GameState->uiData, "ProfilerWindow", {600, 200}, {260,180}, {0.25,0.15, 0.15, 0.5f}, {0.6,0, 0.6, 0.5f});


    debug_data* debugData = (debug_data*)GameState->DebugStorage;
    *GameState->DebugStorageUsed = sizeof(debug_data);
    AssertStr(*GameState->DebugStorageSize > *GameState->DebugStorageUsed, "USED DEBUG MEMORY EXCEEDS MAX DEBUG MEMORY!");


    vec2 posOffset = {};
    snprintf(uiData->debugText + uiData->debugTextOffset, 32, "Profiler"); 
    AddUIText(uiData, window, posOffset, 32, {});
    
    float maxBarHeight = 64;
    posOffset.y += maxBarHeight;

    //on our laptop, we have a 2200Mhz core, which means 2200 * 10^6 = 2 200 000 000 / 60 = 36 666 666
    
    uint64_t maxCyclesPerFrame = 36666666;
    float windowLength = window->hashEntry->halfExtents.x * 2;
    
    int readIndex =  debugData->latestFrameEntryIndex - 1;
    debug_event* frameEvent = debugData->events + debugData->latestFrameEntryIndex;
    uint64_t frameCycles = frameEvent->cycles;

    if(readIndex < 0)readIndex = MAX_DEBUG_EVENTS + readIndex;
    int index = 0;
    int frameCount = 0;
    float starty = posOffset.y;
    
    debug_event tempEvents[256] = {};
    int tempEventsCount = 0;

    int stopStack[256] = {};
    uint64_t accumulatedCycles = 0;
    int lastPoppedDepth = -1;
    
    int stopStackCount = 0;


    while(frameCount < 128){
        int curIndex = readIndex - index;
        if(curIndex < 0){
            curIndex = (MAX_DEBUG_EVENTS + curIndex);
        }
        Assert(curIndex >= 0);
        debug_event* event = debugData->events + (curIndex);
        //skip events for this frame, because we process by the time we already have a start event on the stack
        if(event->frameNum != debugData->frameNum){

            switch(event->type){
                case debug_none         :{}break;
                case debug_timing_start :{
                    debug_event* startEvent = event;
                    debug_event* stopEvent = debugData->events + stopStack[stopStackCount-1];
                    //compare against the latest entry on the stop stack
                    if(stopEvent->depth == startEvent->depth){
                        //we found a match for the function
                        Assert(handmade_strcmp(stopEvent->function, startEvent->function));
                        stopStackCount--;
                        debug_event* tempEvent = tempEvents + tempEventsCount++;
                        Assert(tempEventsCount < 256);
                        tempEvent->cycles = stopEvent->time - startEvent->time;
                        tempEvent->depth = stopEvent->depth;
                        tempEvent->function = stopEvent->function;
                        tempEvent->line = startEvent->line;
                        tempEvent->frameNum = startEvent->frameNum;
                        tempEvent->id = startEvent->id;

                        if(lastPoppedDepth > tempEvent->depth){
                            uint64_t tempCycles = tempEvent->cycles;
                            Assert(tempEvent->cycles >= accumulatedCycles);
                            uint64_t actualCycles = tempEvent->cycles - accumulatedCycles;
                            tempEvent->cycles = actualCycles;
                            accumulatedCycles = tempCycles;
                        }
                        else if(lastPoppedDepth == tempEvent->depth){
                            accumulatedCycles += tempEvent->cycles;
                        }
                        lastPoppedDepth = tempEvent->depth;
                    }

                }break;
                case debug_timing_stop  :{
                    stopStack[stopStackCount++] = curIndex;

                }break;
                case debug_frame        :{
                    //process previous frame
                    uint64_t allEventCycles = 0;
                    uint64_t depth0Cycles = 0;
                    for(int j = 0; j < tempEventsCount; ++j){
                        debug_event* tempEvent = tempEvents + j;
                        if(tempEvent->depth == 0)depth0Cycles += tempEvent->cycles;
                        allEventCycles += tempEvent->cycles;
                    }
                    Assert(allEventCycles == depth0Cycles);
                    float ratio = ((float)allEventCycles / (float)maxCyclesPerFrame);
                    // float ratio = frameCount / (float)128;
                    float height = ratio * maxBarHeight;
                    posOffset.y = starty;
                    posOffset.y -= height;
                    vec2 halfExtents = {(windowLength / (float)128), height};
                    halfExtents *= 0.5f;
                    posOffset.x = ((windowLength / (float)128)) * frameCount;
                    AddUIButton(uiData, window, posOffset, halfExtents, ui_action_increment_int,0, {0,1}, {ratio,1 - ratio,0,0.5f});
                    
                    frameCount++;
                    frameEvent = debugData->events + debugData->latestFrameEntryIndex;
                    frameCycles = frameEvent->cycles;
                    //reset all data, draw the previous frame info

                    stopStackCount = 0;
                    tempEventsCount = 0;
                    lastPoppedDepth = -1;
                    accumulatedCycles = 0;
                }break;
                default                 :{}break;
            }
        }

        index++;
        if(index >= MAX_DEBUG_EVENTS - 1)break;
    }
    //END OF BUTTON DRAWING

    //BEGINNING OF TEXT DRAWING
    posOffset.y = starty;
    frameCount = 0;
    index = 0;
    //draw the raw text for the latest 12 events in the buffer
    while(frameCount < 12){
        int curIndex = readIndex - index;
        if(curIndex < 0){
            curIndex = (MAX_DEBUG_EVENTS + curIndex);
        }
        Assert(curIndex >= 0);
        debug_event* event = debugData->events + (curIndex);
        if(event->depth == 0){//draw a new bar for it in the window 
            float ratio = ((float)event->cycles / (float)maxCyclesPerFrame);
            float height = ratio * maxBarHeight;
            vec2 halfExtents = {(windowLength / (float)128), height};
            halfExtents *= 0.5f;
            posOffset.x = ((windowLength / (float)128)) * frameCount;
            posOffset.x = 0;            
            const char* typeStrStart = "start";
            const char* typeStrStop = "stop";
            const char* typeStrFrame = "frame";
            const char* typeStr = NULL;
            switch(event->type){
                case debug_timing_start:{typeStr = typeStrStart;}break;
                case debug_timing_stop:{typeStr = typeStrStop;}break;
                case debug_frame:{typeStr = typeStrFrame;}break;
                default:{}break;
            }
            snprintf(uiData->debugText + uiData->debugTextOffset, 64, "%-8s, d: %d, id: %d, type: %s", event->function, event->depth, event->id, typeStr); 
            AddUIText(uiData, window, posOffset, 64, {}, ui_type_text_smaller);
            posOffset.y += 20;

            frameCount++;
        }
        index++;
        if(index >= MAX_DEBUG_EVENTS)break;
    }

    posOffset.y += 30;
    posOffset.x = 0;
    snprintf(uiData->debugText + uiData->debugTextOffset, 32, "windowLength: %f", windowLength); 
    AddUIText(uiData, window, posOffset, 32, {}, ui_type_text_smaller);
    posOffset.y += 20;
}
