#include <stdlib.h>
#include <string.h>
#include "matrix.h"

// TODO Matrix-Funktionen implementieren

Matrix createMatrix(unsigned int rows, unsigned int cols)
{
    Matrix matrix;
    if (rows == 0 || cols == 0) {
        matrix.rows = 0;
        matrix.cols = 0;
        matrix.buffer = NULL;
    }
    else
    {
        matrix.rows = rows;
        matrix.cols = cols;
        matrix.buffer = (MatrixType*)malloc(sizeof(MatrixType) * rows * cols);
    }
    return matrix;


}

void clearMatrix(Matrix *matrix)
{
  for (int i = 0; i < matrix->rows; i++)
  { for (int j = 0; j < matrix->cols; j++)
      {
        matrix->cols = 0;
        matrix->rows = 0;
      	matrix->buffer = NULL;
      }
   }
}

void setMatrixAt(MatrixType value, Matrix matrix, unsigned int rowIdx, unsigned int colIdx)
{
    // Sicherheitsprüfung: Sicherstellen, dass der Matrix-Buffer zugewiesen ist und die Indizes innerhalb der Grenzen liegen
    //matrix.buffer == NULL: Prüft, ob überhaupt Speicher für die Matrix zugewiesen wurde
    //rowIdx >= matrix.rows: Prüft, ob der angegebene Zeilenindex nicht größer oder gleich der Gesamtzahl der Zeilen ist
    //colIdx >= matrix.cols: Macht dasselbe für den Spaltenindex
    if (matrix.buffer == NULL || rowIdx >= matrix.rows || colIdx >= matrix.cols) {

        return;
    }

    //value: Das ist der Wert, den Sie in die Matrix schreiben möchten (z.B. 5.0, 10, etc.)
    //matrix: Das ist die Matrix-Struktur selbst, in die der Wert geschrieben werden soll
    //rowIdx, colIdx: Das sind die Zeilen- und Spaltenindizes, an denen der Wert gespeichert werden soll.
    //Wichtig ist, dass diese Indizes bei 0 beginnen (also 0 bis rows-1 und 0 bis cols-1)
    matrix.buffer[rowIdx * matrix.cols + colIdx] = value;

}

MatrixType getMatrixAt(const Matrix matrix, unsigned int rowIdx, unsigned int colIdx)
{
    // Sicherheitsprüfung: Sicherstellen, dass der Matrix-Buffer zugewiesen ist und die Indizes innerhalb der Grenzen liegen
    if (matrix.buffer == NULL || rowIdx >= matrix.rows || colIdx >= matrix.cols) {
        // Wenn der Zugriff ungültig ist wird 0 zurückgegeben
        return (MatrixType)0; // 0 in MatrixType umwandeln (z.B. 0.0 für float/double)
    }

    // Berechnung des 1D-Index: Ebenfalls identisch zur setMatrixAt-Funktion
    //Wert zurückgeben: Sobald der korrekte oneD_index gefunden ist, wird der Wert an matrix.buffer[oneD_index] ausgelesen und als Ergebnis der Funktion zurückgegeben.
    return matrix.buffer[rowIdx * matrix.cols + colIdx];

}

Matrix add(const Matrix matrix1, const Matrix matrix2)
{
    
}

Matrix multiply(const Matrix matrix1, const Matrix matrix2)
{
    
}