void DebugWindowInit() {
    Window  *window = CreateWind();
    DebugWindowID = window->id;
    window->draw_line_numbers = false;
    window->draw_scrollbar = false;
    window->visible = false;
    window->z = 2;
    window->layout = false;
    window->jump_history = false;

    Buffer *buffer = CreateBuffer(SysAllocator, GetUniqueBufferName(WorkDir, "debug"));
    DebugBufferID = buffer->id;
    buffer->no_history = true;
    buffer->special = true;

    View *view = CreateView(buffer->id);
    view->special = true;
    DebugViewID = view->id;
    window->active_view = view->id;
    window->visible = false;
}

void DebugWindowLayout(Rect2I *rect, Int wx, Int wy) {
    Window *n           = GetWindow(DebugWindowID);
    Rect2   screen_rect = Rect0Size((float)wx, (float)wy);
    Vec2    size        = GetSize(screen_rect);

    Rect2 a = CutRight(&screen_rect, 0.3f * size.x);
    Rect2 b = CutTop(&a, 0.4f * size.y);
    Rect2 c = Shrink(b, 20);
    n->document_rect = n->total_rect = ToRect2I(c);
}

void DebugWindowUpdate() {
    ProfileFunction();
    BSet set = GetBSet(DebugWindowID);
    if (!set.window->visible) {
        return;
    }

    BSet active = GetBSet(ActiveWindowID);
    if (active.buffer->id.id == set.buffer->id.id) {
        return;
    }

    BSet main = GetBSet(LastActiveLayoutWindowID);

    Scratch  scratch;
    String   s      = Format(scratch, "wid: %d\nvid: %d\nbid: %d\nframe: %lld\n", (int)main.window->id.id, (int)main.view->id.id, (int)main.buffer->id.id, (long long)FrameID);
    String16 string = ToString16(scratch, s);
    RawReplaceText(set.buffer, GetRange(set.buffer), string);

    float xmouse, ymouse;
    SDL_GetMouseState(&xmouse, &ymouse);
    RawAppendf(set.buffer, "mouse: [%f, %f]\n", roundf(DPIScale * xmouse), roundf(DPIScale * ymouse));

    RawAppendf(set.buffer, "BufferID id = %d\n", main.buffer->id.id);
    RawAppendf(set.buffer, "String name = %S\n", main.buffer->name);
    RawAppendf(set.buffer, "Int change_id = %lld\n", (long long)main.buffer->change_id);
    RawAppendf(set.buffer, "Int user_change_id = %lld\n", (long long)main.buffer->user_change_id);
    RawAppendf(set.buffer, "Int file_mod_time = %lld\n", (long long)main.buffer->file_mod_time);
    RawAppendf(set.buffer, "\n");

    RawAppendf(set.buffer, "U16 *data = %zu\n", main.buffer->data);
    RawAppendf(set.buffer, "Int len = %lld\n", (long long)main.buffer->len);
    RawAppendf(set.buffer, "Int cap = %lld\n", (long long)main.buffer->cap);
    RawAppendf(set.buffer, "Array<Int> line_starts = {len = %lld, cap = %lld, data = %zu}\n", (long long)main.buffer->line_starts.len, (long long)main.buffer->line_starts.cap, main.buffer->line_starts.data);
    RawAppendf(set.buffer, "\n");

    RawAppendf(set.buffer, "Array<HistoryEntry> undo_stack = {len = %lld, cap = %lld, data = %zu}\n", (long long)main.buffer->undo_stack.len, (long long)main.buffer->undo_stack.cap, main.buffer->undo_stack.data);
    RawAppendf(set.buffer, "Array<HistoryEntry> redo_stack = {len = %lld, cap = %lld, data = %zu}\n", (long long)main.buffer->redo_stack.len, (long long)main.buffer->redo_stack.cap, main.buffer->redo_stack.data);
    RawAppendf(set.buffer, "int edit_phase = %d", main.buffer->edit_phase);
    RawAppendf(set.buffer, "\n");

    RawAppendf(set.buffer, "int no_history = %d\n", main.buffer->no_history);
    RawAppendf(set.buffer, "int no_line_starts = %d\n", main.buffer->no_line_starts);
    RawAppendf(set.buffer, "int dirty = %d\n", main.buffer->dirty);
    RawAppendf(set.buffer, "int changed_on_disk = %d\n", main.buffer->changed_on_disk);
    RawAppendf(set.buffer, "int garbage = %d\n", main.buffer->garbage);
}

void Command_ToggleDebug() {
    Window *window = GetWindow(DebugWindowID);
    window->visible = !window->visible;
} RegisterCommand(Command_ToggleDebug, "ctrl-0");
