const std = @import("std");
pub const c = @import("c.zig").c;

pub const Window = opaque {
    pub inline fn warpMouseInWindow(window: *Window, x: f32, y: f32) void {
        return c.SDL_WarpMouseInWindow(window, x, y);
    }

    pub inline fn setWindowRelativeMouseMode(window: *Window, enabled: bool) bool {
        return @bitCast(c.SDL_SetWindowRelativeMouseMode(window, @bitCast(enabled)));
    }

    pub inline fn getWindowRelativeMouseMode(window: *Window) bool {
        return @bitCast(c.SDL_GetWindowRelativeMouseMode(window));
    }
};

pub const Surface = opaque {
    pub inline fn createColorCursor(surface: *Surface, hot_x: c_int, hot_y: c_int) ?*Cursor {
        return c.SDL_CreateColorCursor(surface, hot_x, hot_y);
    }
};

pub const MouseID = u32;

pub const Cursor = opaque {
    pub inline fn setCursor(cursor: *Cursor) bool {
        return @bitCast(c.SDL_SetCursor(cursor));
    }

    pub inline fn destroyCursor(cursor: *Cursor) void {
        return c.SDL_DestroyCursor(cursor);
    }
};

pub const SystemCursor = enum(c_int) {
    systemCursorDefault, //Default cursor. Usually an arrow.
    systemCursorText, //Text selection. Usually an I-beam.
    systemCursorWait, //Wait. Usually an hourglass or watch or spinning ball.
    systemCursorCrosshair, //Crosshair.
    systemCursorProgress, //Program is busy but still interactive. Usually it's WAIT with an arrow.
    systemCursorNwseResize, //Double arrow pointing northwest and southeast.
    systemCursorNeswResize, //Double arrow pointing northeast and southwest.
    systemCursorEwResize, //Double arrow pointing west and east.
    systemCursorNsResize, //Double arrow pointing north and south.
    systemCursorMove, //Four pointed arrow pointing north, south, east, and west.
    systemCursorNotAllowed, //Not permitted. Usually a slashed circle or crossbones.
    systemCursorPointer, //Pointer that indicates a link. Usually a pointing hand.
    systemCursorNwResize, //Window resize top-left. This may be a single arrow or a double arrow like NWSE_RESIZE.
    systemCursorNResize, //Window resize top. May be NS_RESIZE.
    systemCursorNeResize, //Window resize top-right. May be NESW_RESIZE.
    systemCursorEResize, //Window resize right. May be EW_RESIZE.
    systemCursorSeResize, //Window resize bottom-right. May be NWSE_RESIZE.
    systemCursorSResize, //Window resize bottom. May be NS_RESIZE.
    systemCursorSwResize, //Window resize bottom-left. May be NESW_RESIZE.
    systemCursorWResize, //Window resize left. May be EW_RESIZE.
    systemCursorCount,
};

pub const MouseWheelDirection = enum(c_int) {
    mousewheelNormal, //The scroll direction is normal
    mousewheelFlipped, //The scroll direction is flipped / natural
};

pub const MouseButtonFlags = packed struct(u32) {
    buttonLeft: bool = false,
    buttonMiddle: bool = false,
    buttonX1: bool = false,
    pad0: u28 = 0,
    rsvd: bool = false,
};

pub inline fn hasMouse() bool {
    return @bitCast(c.SDL_HasMouse());
}

pub inline fn getMice(count: *c_int) ?*MouseID {
    return c.SDL_GetMice(@ptrCast(count));
}

pub inline fn getMouseNameForID(instance_id: MouseID) [*c]const u8 {
    return c.SDL_GetMouseNameForID(instance_id);
}

pub inline fn getMouseFocus() ?*Window {
    return c.SDL_GetMouseFocus();
}

pub inline fn getMouseState(x: *f32, y: *f32) MouseButtonFlags {
    return @bitCast(c.SDL_GetMouseState(@ptrCast(x), @ptrCast(y)));
}

pub inline fn getGlobalMouseState(x: *f32, y: *f32) MouseButtonFlags {
    return @bitCast(c.SDL_GetGlobalMouseState(@ptrCast(x), @ptrCast(y)));
}

pub inline fn getRelativeMouseState(x: *f32, y: *f32) MouseButtonFlags {
    return @bitCast(c.SDL_GetRelativeMouseState(@ptrCast(x), @ptrCast(y)));
}

pub inline fn warpMouseGlobal(x: f32, y: f32) bool {
    return @bitCast(c.SDL_WarpMouseGlobal(x, y));
}

pub inline fn captureMouse(enabled: bool) bool {
    return @bitCast(c.SDL_CaptureMouse(@bitCast(enabled)));
}

pub inline fn createCursor(data: [*c]const u8, mask: [*c]const u8, w: c_int, h: c_int, hot_x: c_int, hot_y: c_int) ?*Cursor {
    return c.SDL_CreateCursor(data, mask, w, h, hot_x, hot_y);
}

pub inline fn createSystemCursor(id: SystemCursor) ?*Cursor {
    return c.SDL_CreateSystemCursor(id);
}

pub inline fn getCursor() ?*Cursor {
    return c.SDL_GetCursor();
}

pub inline fn getDefaultCursor() ?*Cursor {
    return c.SDL_GetDefaultCursor();
}

pub inline fn showCursor() bool {
    return @bitCast(c.SDL_ShowCursor());
}

pub inline fn hideCursor() bool {
    return @bitCast(c.SDL_HideCursor());
}

pub inline fn cursorVisible() bool {
    return @bitCast(c.SDL_CursorVisible());
}
