#include "includes.h"

int getrand(int min, int max)
{
    return (int)rand() / (RAND_MAX + 1.0) * (max - min) + min;
}

matrix2d* create_matrix2d(unsigned int x, unsigned int y)
{
    matrix2d* mat = (matrix2d*)malloc(sizeof(matrix2d));
    mat->ptr = (void***)malloc(sizeof(void**) * x);
    for (int i = 0; i < x; i++)
        mat->ptr[i] = (void**)malloc(sizeof(void*) * y);
    for (int i = 0; i < x; i++)
        for (int j = 0; j < y; j++)
            mat->ptr[i][j] = (void*)create_led();
    *((unsigned int*)&(mat->x)) = x;
    *((unsigned int*)&(mat->y)) = y;
    return mat;
}

void deconstruct_matrix2d( matrix2d* mat) 
{
    for (int i = 0; i < mat->x; i++){
        for (int j = 0; j < mat->y; j++)
            free(mat->ptr[i][j]);
        free(mat->ptr[i]);
    }
    free(mat->ptr);
    free(mat);
}

matrix2d* get_row_matrix2d(matrix2d* mat, int y)
{
    if (y >= mat->y)
        return NULL;
    matrix2d* res = create_matrix2d( mat->x, 1);
    for (int x = 0; x < mat->x; x++)
        memcpy(res->ptr[x][0], mat->ptr[x][y], sizeof(rgbled));
    return res;
}

matrix2d* get_column_matrix2d(matrix2d* mat, int x)
{
    if (x >= mat->x)
        return NULL;
    matrix2d* res = create_matrix2d(1, mat->y);
    for (int y = 0; y < mat->y; y++)
        memcpy(res->ptr[0][y], mat->ptr[x][y], sizeof(rgbled));
    return res;
}

void print_matrix2d(matrix2d* mat)
{
    for (int y = 0; y < mat->y; y++) {
        for (int x = 0; x < mat->x; x++) {
            print_colorHEX((rgbled*)mat->ptr[x][y]);
            putchar(' ');
        }
        putchar('\n');
    }
}

void fill_rand_matrix2d(matrix2d* mat)
{
    for (int y = 0; y < mat->y; y++)
        for (int x = 0; x < mat->x; x++) {
            set_R(mat->ptr[x][y], getrand(0, 255));
            set_G(mat->ptr[x][y], getrand(0, 255));
            set_B(mat->ptr[x][y], getrand(0, 255));
        }
}

matrix2d* transpond_mtrx(matrix2d* mat)
{
    matrix2d* res = create_matrix2d(mat->y, mat->x);
    for (int y = 0; y < mat->y; y++)
        for (int x = 0; x < mat->x; x++)
            memcpy(res->ptr[y][x], mat->ptr[x][y], sizeof(rgbled)); 
    return res;
}

bool equal_mtrx(matrix2d* matA, matrix2d* matB)
{
    if (matA->x != matB->x || matA->y != matB->y)
        return false;
    for (int x = 0; x < matA->x; x++)
        for (int y = 0; y < matA->y; y++) {
            rgbled* ledA = (rgbled*)matA->ptr[x][y];
            rgbled* ledB = (rgbled*)matB->ptr[x][y];
            if ((ledA->rgbd != ledB->rgbd) || (ledA->efg != ledB->efg))
                return false;
        }
    return true;
}

bool not_equal_mtrx(matrix2d* matA, matrix2d* matB)
{
    if (matA->x != matB->x || matA->y != matB->y)
        return true;
    for (int x = 0; x < matA->x; x++)
        for (int y = 0; y < matA->y; y++) {
            rgbled* ledA = (rgbled*)matA->ptr[x][y];
            rgbled* ledB = (rgbled*)matB->ptr[x][y];
            if ((ledA->rgbd == ledB->rgbd) && (ledA->efg == ledB->efg))
                return false;
        }
    return true;
}

void set_elem_matrix2d(matrix2d* mat, void* elem, unsigned int x, unsigned int y)
{
    free(mat->ptr[x][y]);
    mat->ptr[x][y] = elem;
}
