/**
 * Copyright (c) 2021 Dominic Masters
 * 
 * This software is released under the MIT License.
 * https://opensource.org/licenses/MIT
 */

#pragma once
#include "../libs.h"
#include "../util/math.h"
#include "align.h"

/** Maximum number of columns a grid can have */
#define GRID_COLUMN_COUNT_MAX 16
/** Maximum number of rows a grid can have */
#define GRID_ROW_COUNT_MAX GRID_COLUMN_COUNT_MAX

/** Cell size for "auto", basically to fill the remaining space evenly */
#define GRID_CEL_SIZE_AUTO -1

/** Definitio of a grid */
typedef struct {
  /** Count of columns/rows in the grid */
  uint8_t columns, rows;

  /** Cell Definitions, used to control how the cells will size themselves */
  float columnDefinitions[GRID_COLUMN_COUNT_MAX];
  float rowDefinitions[GRID_COLUMN_COUNT_MAX];
  
  /** Settings to control gutters (space between cells) and border (of grid) */
  float gutterX, gutterY;
  float borderX, borderY;

  /** Calculated sizes and positions for each cell */
  float columnSizes[GRID_COLUMN_COUNT_MAX];
  float columnPositions[GRID_COLUMN_COUNT_MAX];
  float rowSizes[GRID_ROW_COUNT_MAX];
  float rowPositions[GRID_COLUMN_COUNT_MAX];

  /** Cached size of the grid */
  float width, height;
} grid_t;

/**
 * Initialize a grid system.
 * 
 * @param grid Grid system to initialize.
 */
void gridInit(grid_t *grid);

/**
 * Recalculate the cell size and positions.
 * 
 * @param grid Grid to recalculate for.
 */
void gridRecalculate(grid_t *grid);

/**
 * Resize (and recalculate) a grid.
 * 
 * @param grid Grid to resize.
 * @param width Width to use.
 * @param height Height to use.
 */
void gridResize(grid_t *grid, float width, float height);

/**
 * Get the dimensions of a particular cell and span.
 * 
 * @param grid Grid to get from.
 * @param col Starting column.
 * @param row Starting row.
 * @param columns Count of columns the cell spans.
 * @param rows Count of rows the cell spans.
 * @param x Pointer to output X float.
 * @param y Pointer to output Y float
 * @param width Pointer to output width float.
 * @param height Pointer to output height float.
 */
void gridGetChild(
  grid_t *grid, uint8_t col, uint8_t row, uint8_t columns, uint8_t rows,
  float *x, float *y, float *width, float *height
);

/**
 * Align a child within its set cell.
 * 
 * @param grid Grid to use when aligning.
 * @param col Starting column.
 * @param row Starting row.
 * @param columns Count of columns the cell spans.
 * @param rows Count of rows the cell spans.
 * @param alignX Alignment flags for the X axis.
 * @param alignY Alignment flags for the Y axis.
 * @param width Current width of the child.
 * @param height Current height of the child.
 * @return The alignment information to align the child within the cell.
 */
align_t gridGetAndAlignChild(
  grid_t *grid, uint8_t col, uint8_t row, uint8_t columns, uint8_t rows,
  uint8_t alignX, uint8_t alignY, float width, float height
);