module ttf

/**********************************************************************
*
* Common data for the module
*
* Copyright (c) 2021 Dario Deledda. All rights reserved.
* Use of this source code is governed by an MIT license
* that can be found in the LICENSE file.
*
* Note:
*
* TODO:
**********************************************************************/
import os
import math

// text align
pub enum Text_align {
	left
	center
	right
	justify
}

// draw style
pub enum Style {
	outline
	outline_aliased
	filled
	raw
}

/******************************************************************************
*
* DEBUG Utility
*
******************************************************************************/
const debug_flag = false

fn dprintln(txt string) {
	if debug_flag {
		println(txt)
	}
}

/******************************************************************************
*
* Utility
*
******************************************************************************/
// format_texture transforms the bitmap from one layer to color layers
fn (mut bmp BitMap) format_texture() {
	r := u8(bmp.color >> 24)
	g := u8((bmp.color >> 16) & 0xFF)
	b := u8((bmp.color >> 8) & 0xFF)
	a := u8(bmp.color & 0xFF)

	b_r := u8(bmp.bg_color >> 24)
	b_g := u8((bmp.bg_color >> 16) & 0xFF)
	b_b := u8((bmp.bg_color >> 8) & 0xFF)
	b_a := u8(bmp.bg_color & 0xFF)

	// transform buffer in a texture
	x := bmp.buf
	unsafe {
		mut i := 0
		for i < bmp.buf_size {
			data := x[i]
			if data > 0 {
				x[i + 0] = r
				x[i + 1] = g
				x[i + 2] = b
				// alpha
				x[i + 3] = u8(u16(u16(a) * data) >> 8)
			} else {
				x[i + 0] = b_r
				x[i + 1] = b_g
				x[i + 2] = b_b
				x[i + 3] = b_a
			}
			i += 4
		}
	}
}

// save_as_ppm saves the `BitMap` data in .ppm file format to `file_name`.
pub fn (mut bmp BitMap) save_as_ppm(file_name string) {
	tmp_buf := bmp.buf
	mut buf := unsafe { malloc_noscan(bmp.buf_size) }
	unsafe { vmemcpy(buf, tmp_buf, bmp.buf_size) }
	bmp.buf = buf

	bmp.format_texture()
	npixels := bmp.width * bmp.height
	mut f_out := os.create(file_name) or { panic(err) }
	f_out.writeln('P3') or { panic(err) }
	f_out.writeln('${bmp.width} ${bmp.height}') or { panic(err) }
	f_out.writeln('255') or { panic(err) }
	for i in 0 .. npixels {
		pos := i * bmp.bp
		unsafe {
			c_r := bmp.buf[pos]
			c_g := bmp.buf[pos + 1]
			c_b := bmp.buf[pos + 2]
			f_out.write_string('${c_r} ${c_g} ${c_b} ') or { panic(err) }
		}
	}
	f_out.close()

	unsafe {
		free(buf)
	}
	bmp.buf = tmp_buf
}

// get_raw_bytes returns the raw bytes of the bitmap.
pub fn (mut bmp BitMap) get_raw_bytes() []u8 {
	mut f_buf := []u8{len: bmp.buf_size / 4}
	mut i := 0
	for i < bmp.buf_size {
		unsafe {
			f_buf[i >> 2] = *(bmp.buf + i)
		}
		i += 4
	}
	return f_buf
}

// save_raw_data saves the raw data to `file_name`.
pub fn (mut bmp BitMap) save_raw_data(file_name string) {
	os.write_file_array(file_name, bmp.get_raw_bytes()) or { panic(err) }
}

//
// Math functions
//
// integer part of x
@[inline]
fn ipart(x f32) f32 {
	return f32(math.floor(x))
}

@[inline]
fn round(x f32) f32 {
	return ipart(x + 0.5)
}

// fractional part of x
@[inline]
fn fpart(x f32) f32 {
	return x - f32(math.floor(x))
}

@[inline]
fn rfpart(x f32) f32 {
	return 1 - fpart(x)
}

/******************************************************************************
*
* Colors
*
******************************************************************************/

// @[inline]
// pub fn (mut dev BitMap) get_color(x int, y int) (int, int, int, int){
// 	if x < 0 || x >= dev.width || y < 0 || y >= dev.height {
// 		return 0,0,0,0
// 	}
// 	mut i := (x + y * dev.width)*dev.bp
// 	unsafe{
// 		return dev.buf[i], dev.buf[i+1], dev.buf[i+2], dev.buf[i+3]
// 	}
// }

// @[inline]
// pub fn (mut dev BitMap) get_color_u32(x int, y int) u32{
// 	r, g, b, a := dev.get_color(x, y)
// 	unsafe{
// 		return u32(r<<24) | u32(g<<16) | u32(b<<8) | u32(a)
// 	}
// }

/******************************************************************************
*
* Drawing
*
******************************************************************************/

// color_multiply_alpha multiplies color `c`'s alpha channel with the `level` value.
@[inline]
pub fn color_multiply_alpha(c u32, level f32) u32 {
	return u32(f32(c & 0xFF) * level)
}

// color_multiply multiplies R,G,B channels of color `c` with the `level` value.
@[inline]
pub fn color_multiply(c u32, level f32) u32 {
	mut r := (f32((c >> 24) & 0xFF) / 255.0) * level
	mut g := (f32((c >> 16) & 0xFF) / 255.0) * level
	mut b := (f32((c >> 8) & 0xFF) / 255.0) * level
	mut a := (f32(c & 0xFF) / 255.0) * level
	r = if r > 1.0 { 1.0 } else { r }
	g = if g > 1.0 { 1.0 } else { g }
	b = if b > 1.0 { 1.0 } else { b }
	a = if a > 1.0 { 1.0 } else { a }

	return (u32(r * 255) << 24) | (u32(g * 255) << 16) | (u32(b * 255) << 8) | u32(a * 255)
}
