from time import ticks_ms, sleep
from math import log, ceil, floor
from bme680.bme680 import BME680_I2C
from mch22 import exit_python
from machine import SoftI2C, Pin
import display
import buttons

bme = BME680_I2C(SoftI2C(scl=Pin(21), sda=Pin(22)))

BACKGROUND = 0x491D88
PALETTE_0 = 0xFEC859
PALETTE_1 = 0xFA448C
PALETTE_2 = 0x331A38
PALETTE_3 = 0x43B5A0

IIR_FILTER_TIME_S = 5


def reboot(pressed):
    if pressed:
        exit_python()


buttons.attach(buttons.BTN_HOME, reboot)

# define functions to round, floor and ceil with float resolutions
def round_res(num, res):
    return round(num / res) * res


def floor_res(num, res):
    return floor(num / res) * res


def ceil_res(num, res):
    return ceil(num / res) * res


def map_vals_fn(in_min, in_max, out_min, out_max):
    scaleFactor = float(out_max - out_min) / float(in_max - in_min)

    def map_vals(value):
        return out_min + (value - in_min) * scaleFactor

    return map_vals


# generic function to draw samples in a given area on the display
def draw_samples(
    samples,
    x_min=0,
    x_max=display.width(),
    y_min=0,
    y_max=display.height(),
    padding=0.05,
    grid=True,
    n_grid=5,
):
    keys, values = list(zip(*samples))

    min_key = min(keys)
    max_key = max(keys)
    min_value = min(values)
    max_value = max(values)

    width = x_max - x_min
    height = y_max - y_min

    x_map_fn = map_vals_fn(
        min_key, max_key, x_min + padding * width, x_min + (1 - padding) * width
    )
    y_map_fn = map_vals_fn(
        max_value,
        min_value,
        x_min + padding * height,
        x_min + (1 - padding) * height,
    )

    xs = map(int, map(x_map_fn, keys))
    ys = map(int, map(y_map_fn, values))

    nodes = list(zip(xs, ys))

    if grid:
        key_res = 10 ** round(log(max_key - min_key, 10)) / n_grid
        value_res = 10 ** round(log(max_value - min_value, 10)) / n_grid

        min_key_grid = round_res(min_key, key_res)
        min_value_grid = round_res(min_value, value_res)

        n_key_grids = ceil((max_key - min_key_grid) / key_res + 0.5)
        n_value_grids = ceil((max_value - min_value_grid) / value_res + 0.5)

        for x_grid_idx in range(n_key_grids):
            x = x_map_fn(min_key_grid + x_grid_idx * key_res)
            display.drawLine(x, y_min, x, y_max, PALETTE_2)

        for y_grid_idx in range(n_value_grids):
            y = y_map_fn(min_value_grid + y_grid_idx * value_res)
            display.drawLine(x_min, y, x_max, y, PALETTE_2)

    for idx in range(len(nodes) - 1):
        display.drawLine(
            nodes[idx][0],
            nodes[idx][1],
            nodes[idx + 1][0],
            nodes[idx + 1][1],
            PALETTE_3,
        )

samples = [(ticks_ms(), bme.pressure)]

while True:
    try:
        display.drawFill(BACKGROUND)
        print(bme.temperature)
        sleep(30)
    except:
        exit_python()