#pragma once
#include "../repository/repository.h"
#include "../undo_module/undo_controller/undo_controller.h"

typedef struct{
    Repository* repository;
    UndoController* undo_controller;
} Controller;

/*
    Constructor for the Controller
    Input: repository - Repository*
    Output: a pointer to the newly created controller
*/
Controller* _Controller_Constructor(Repository* repository,UndoController* undo_controller);

/*
    Destructor for the Controller
    Input: controller - Controller*
    Output: -
*/
void _Controller_Destructor(Controller* controller);

/*
    Adds an element to the repository
    Input: controller - Controller*
           name - char* - the name of the material
           supplier - char* - the supplier of the material
           quantity - int - the quantity of the material
           day - int - the day of the expiration date
           month - int - the month of the expiration date
           year - int - the year of the expiration date
    Output: 1 - if the element was added
            0 - if the element was not added
            2 - if the element was not added because it already exists
*/
int _Controller_add(Controller* controller, char *name, char *supplier, int quantity, int day, int month, int year);

/*
    Deletes an element from the repository
    Input: controller - Controller*
           name - char* - the name of the material
           supplier - char* - the supplier of the material
           day - int - the day of the expiration date
           month - int - the month of the expiration date
           year - int - the year of the expiration date
    Output: 1 - if the element was deleted
            0 - if the element was not deleted
*/
int _Controller_delete(Controller* controller, char *name, char *supplier, int day, int month, int year);

/*
    Updates an element from the repository
    Input: controller - Controller*
           name - char* - the name of the material
           supplier - char* - the supplier of the material
           quantity - int - the quantity of the material
           day - int - the day of the expiration date
           month - int - the month of the expiration date
           year - int - the year of the expiration date
    Output: 1 - if the element was updated
            0 - if the element was not updated
*/
int _Controller_update(Controller* controller,char *name, char *supplier, int quantity, int day, int month, int year);

/*
    Gets the lenght of the repository
    Input: controller - Controller*
    Output: int - the lenght of the repository
*/
int _Controller_getLenght(Controller* controller);

/*
    Gets an element from the repository
    Input: controller - Controller*
           index - int - the index of the element to be returned
    Output: Material* - the element at the given index
            NULL - if the index is invalid
*/
Material* _Controller_getItem(Controller* controller,int index);

/*
    Gets the expired material matching the given string
    Input: controller - Controller*
           string - char* - the string to be matched
           lenght - int* - the lenght of the retruned array
    Output: Material** - the array of expired material matching the given string
*/
Material** _Controller_getExpiredMaterial(Controller* controller,char* string,int* lenght);

/*
    Gets the material with quantity less than the given quantity
    Input: controller - Controller*
           quantity - int - the quantity to be matched
    Output: Vector* - the vector of material with the given quantity
*/
Vector* _Controller_getShortSupplyItems(Controller* controller, int quantity);

/*
    Undoes the last operation
    Input: controller - Controller*
    Output: 1 - if the operation was undone
            0 - if the operation was not undone
*/
int _Controller_undo(Controller* controller);

/*
    Redoes the last operation
    Input: controller - Controller*
    Output: 1 - if the operation was redone
            0 - if the operation was not redone
*/
int _Controller_redo(Controller* controller);