.{draw_pixel, screenidx, Transform, Point, Rect, Buffer, FB_WIDTH} := @use("rel:lib.hb")
ColorBGRA := @use("rel:color.hb").ColorBGRA
math := @use("../../../libraries/stn/src/lib.hb").math

/* draws a filled rectangle to the screen
   will be optimised later */
rect_fill := fn(buffer: Buffer, pos: Point, tr: Transform, color: ColorBGRA): void {
	n := 0
	loop if n == tr.height * tr.width break else {
		*(buffer.write + screenidx(.(n % tr.width + pos.x, n / tr.width + pos.y))) = color
		n += 1
	}
	return
}
/* draws a wireframe rectangle to the screen
   will also be optimised later */
rect_line := fn(buffer: Buffer, pos: Point, tr: Transform, color: ColorBGRA, thickness: int): void {
	t := 0
	y := 0
	x := 0
	loop if t == thickness break else {
		y = pos.y
		x = pos.x
		loop if y == pos.y + tr.height break else {
			*(buffer.write + pos.x + t + FB_WIDTH * y) = color;
			*(buffer.write + pos.x + tr.width - t + FB_WIDTH * y) = color
			y += 1
		}
		loop if x == pos.x + tr.width break else {
			*(buffer.write + x + (pos.y + t) * FB_WIDTH) = color;
			*(buffer.write + x + (pos.y + tr.height - t) * FB_WIDTH) = color
			x += 1
		}
		t += 1
	}
	return
}

// do not use, use line() instead
line_low := fn(buffer: Buffer, p0: Point, p1: Point, color: ColorBGRA): void {
	dx := p1.x - p0.x
	dy := p1.y - p0.y
	yi := 1
	if dy < 0 {
		yi = 0 - 1
		dy = 0 - dy
	}
	D := 2 * dy - dx
	y := p0.y
	x := p0.x
	loop if x == p1.x break else {
		*(buffer.write + x + y * FB_WIDTH) = color
		if D > 0 {
			y += yi
			D += 2 * (dy - dx)
		} else {
			D += 2 * dy
		}
		x += 1
	}
	return
}
// do not use, use line() instead
line_high := fn(buffer: Buffer, p0: Point, p1: Point, color: ColorBGRA): void {
	dx := p1.x - p0.x
	dy := p1.y - p0.y
	xi := 1
	if dy < 0 {
		xi = 0 - 1
		dx = 0 - dx
	}
	D := 2 * dx - dy
	x := p0.x
	y := p0.y
	loop if y == p1.y break else {
		*(buffer.write + x + y * FB_WIDTH) = color
		if D > 0 {
			x += xi
			D += 2 * (dx - dy)
		} else {
			D += 2 * dx
		}
		y += 1
	}
	return
}

/* implementation of Bresenham's line algorithm
   TODO: thickness, might need better math library */
line := fn(buffer: Buffer, p0: Point, p1: Point, color: ColorBGRA, thickness: int): void {
	if math.abs(p1.y - p0.y) < math.abs(p1.x - p0.x) {
		if p0.x > p1.x {
			line_low(buffer, p1, p0, color)
		} else {
			line_low(buffer, p0, p1, color)
		}
	} else {
		if p0.y > p1.y {
			line_high(buffer, p1, p0, color)
		} else {
			line_high(buffer, p0, p1, color)
		}
	}
	return
}

// theoretically draws a wireframe polygon to the screen. untested.
tri_line := fn(buffer: Buffer, p0: Point, p1: Point, p2: Point, color: ColorBGRA, thickness: int): void {
	line(buffer, p0, p1, color, thickness)
	line(buffer, p1, p2, color, thickness)
	line(buffer, p2, p0, color, thickness)
	return
}