#ifndef REG_PROCESOS_C
#define REG_PROCESOS_C

#include <RegProcesos.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>

char* ObtenerNomBin	(char *ruta)
{
	char *result, *iter;

	result = ruta;
	iter = ruta;
	
	while (*iter != '\0') 
	{
		if ( *iter == '/')
			result = iter + 1;
		iter++;
	}

	return result;
}

void crearTablaProceso(RegProcesos *tabla_procesos) 
{
	tabla_procesos->tope = 0;
}

// Pre: No existe un proceso con clave 'clave'
// Pos: Retorna -1 en caso de que la tabla este llena
int crearProceso(char *clave, char *ruta, char *descripcion,RegProcesos *tabla_procesos )
{
	int indice;
	
	if (tabla_procesos->tope == MAX_PROCESOS)
		return -1;
	
	indice = tabla_procesos->tope;
	
	tabla_procesos->proceso[indice].corriendo = 0;
	tabla_procesos->proceso[indice].cant_pedidos = 0; 
	strcpy(tabla_procesos->proceso[indice].clave,clave);
	strcpy(tabla_procesos->proceso[indice].ruta,ruta);
	strcpy(tabla_procesos->proceso[indice].descripcion,descripcion);
	++tabla_procesos->tope;
	return 1;
	
}


// Pre: Existe un proceso con clave 'clave'
int eliminarProceso(char *clave, RegProcesos *tabla_procesos )
{
	
	int i = 0;
	int j;
	int tope = tabla_procesos->tope-1;
	
	while (strcmp(tabla_procesos->proceso[i].clave,clave)!=0)
		i++;
	
	strcpy( tabla_procesos->proceso[i].clave, tabla_procesos->proceso[tope].clave);
	strcpy( tabla_procesos->proceso[i].ruta, tabla_procesos->proceso[tope].ruta);
	strcpy( tabla_procesos->proceso[i].descripcion, tabla_procesos->proceso[tope].descripcion);
	
	tabla_procesos->proceso[i].corriendo = tabla_procesos->proceso[tope].corriendo;
	tabla_procesos->proceso[i].fecha_ejecucion = tabla_procesos->proceso[tope].fecha_ejecucion;
	tabla_procesos->proceso[i].pid = tabla_procesos->proceso[tope].pid;
	tabla_procesos->proceso[i].padre_del_pichon = tabla_procesos->proceso[tope].padre_del_pichon;
	
	tabla_procesos->proceso[i].cant_pedidos = tabla_procesos->proceso[tope].cant_pedidos;
	
	for(j=0; j<	tabla_procesos->proceso[tope].cant_pedidos; j++)
		strcpy(tabla_procesos->proceso[i].indice_recurso[j], tabla_procesos->proceso[tope].indice_recurso[j] );
	
	tabla_procesos->tope--;
	return 1;
}

// Precondicion: Existe un proceso con clave 'clave'
// Retorna: -1 en caso de error
int iniciarProceso(char *clave,pid_t pid,pid_t padre_del_pichon ,RegProcesos *tabla_procesos )
{
	time_t t;
	int i = 0;
	time(&t);
	
	while (strcmp(tabla_procesos->proceso[i].clave,clave) != 0)
		i++;
	if (tabla_procesos->proceso[i].corriendo)
		return -1;
	else {
		tabla_procesos->proceso[i].corriendo = 1;
		tabla_procesos->proceso[i].pid = pid;
		tabla_procesos->proceso[i].padre_del_pichon = padre_del_pichon;
		tabla_procesos->proceso[i].fecha_ejecucion=t;
		return 1;
	}
}
// Pre: Existe un proceso con clave 'clave'
// Pre: El proceso esta corriendo
int matarProceso(char *clave, RegProcesos *tabla_procesos)
{
	int i = 0;
	
	while (strcmp(tabla_procesos->proceso[i].clave,clave) != 0)
		i++;

	tabla_procesos->proceso[i].corriendo = 0;
	return 1;
}

// Precondicion: Existe un proceso con clave 'clave' y esta iniciado
pid_t getpidProceso(char *clave,RegProcesos *tabla_procesos) {
	int i = 0;

	while (strcmp(tabla_procesos->proceso[i].clave,clave)!=0)
		i++;
	return tabla_procesos->proceso[i].pid;
}

// Precondicion: Existe un proceso con clave 'clave' y esta iniciado
pid_t getpidPadrePichonProceso(char *clave,RegProcesos *tabla_procesos) {
	int i = 0;

	while (strcmp(tabla_procesos->proceso[i].clave,clave)!=0)
		i++;
	return tabla_procesos->proceso[i].pid;
}

int obtener_indice_proceso( char *clave,RegProcesos *tabla_procesos)
{
	int i = 0;

	while (strcmp(tabla_procesos->proceso[i].clave,clave)!=0)
		i++;
	return i;
}

int cantidad_recursos_asignados (char *clave,RegProcesos *tabla_procesos)
{
	int i = 0;

	while (strcmp(tabla_procesos->proceso[i].clave,clave)!=0)
		i++;

	return tabla_procesos->proceso[i].cant_pedidos;
}

char* obtenerRutaProceso(char *clave, RegProcesos *tabla_procesos)
{
	int indice;
	indice = obtener_indice_proceso(clave, tabla_procesos);
	return tabla_procesos->proceso[indice].ruta;
}

// pre: que se puede asignar
void asignar_recurso_a_proceso (char *clave_proc,char* clave_recur, RegProcesos *tabla_procesos)
{
	int i;
	int indice;
	
	indice = obtener_indice_proceso(clave_proc, tabla_procesos);
	i = tabla_procesos->proceso[indice].cant_pedidos;
	
	tabla_procesos->proceso[indice].cant_pedidos++;
	strcpy(tabla_procesos->proceso[indice].indice_recurso[i], clave_recur);
	
}
//Precondicion: Existe un proceso con clave 'clave_proc' que tiene asignado el 
// recurso clave_recur
// OJO que el recurso no se da cuenta que no esta desasignado
void desasignar_recurso_a_proceso (char *clave_proc,char* clave_recur, RegProcesos *tabla_procesos)
{
	int i,j;
	int indice;
	
	indice = obtener_indice_proceso(clave_proc, tabla_procesos);
	i = tabla_procesos->proceso[indice].cant_pedidos-1;
	
	j = 0;
	// busco donde esta el recurso en el proceso
	while ( strcmp(tabla_procesos->proceso[indice].indice_recurso[j], clave_recur) != 0)
		j++;
	// swap con el tope
	strcpy(tabla_procesos->proceso[indice].indice_recurso[j], tabla_procesos->proceso[indice].indice_recurso[i]);
	tabla_procesos->proceso[indice].cant_pedidos--; //Bajo la cantidad de recursos del proc.	
}

// Pre: Existe un proceso con clave 'clave'
// Pos: 1: sii el proceso esta corriendo
// 		0: en caso contrario
int corriendoProceso(char *clave, RegProcesos *tabla_procesos)
{
	int i = 0;
	while (strcmp(tabla_procesos->proceso[i].clave,clave)!=0)
		i++;
	return tabla_procesos->proceso[i].corriendo;
}

int existeProceso(char *clave,RegProcesos *tabla_procesos) 
{
	int i = 0;
	int tope = tabla_procesos->tope;
	
	while (i != tope && strcmp(tabla_procesos->proceso[i].clave,clave)!=0)
		i++;
	if (i == tope)
		return 0;
	return 1;
}
//Pos: 1: Sii el recurso esta asignado al Proceso
//		0: caso contrario
int recursoEstaAsignadoAProceso(char *clave_proc, char *clave_recurso, RegProcesos *tabla_procesos)
{
	int i, indice;
	int result = 0;
	i = obtener_indice_proceso(clave_proc, tabla_procesos);
	
	for (indice = 0; !result && indice < tabla_procesos->proceso[i].cant_pedidos; indice++)
	{
		if (strcmp(tabla_procesos->proceso[i].indice_recurso[indice],clave_recurso) == 0)
			result = 1;
	}
	return result;
}


// Precondicion: Existe un proceso con clave 'clave'
int consultarProceso(char *clave, RegProcesos *tabla_procesos,char *linea)
{
	int i = 0;
	int j = 0;
	while (strcmp(tabla_procesos->proceso[i].clave,clave)!=0)
		i++;
	
	sprintf(linea,"Proceso %s %s", clave, tabla_procesos->proceso[i].corriendo ? "iniciado":"no iniciado");
	strcat(linea, "\nRecursos Asignados: ");
	if (tabla_procesos->proceso[i].corriendo)
	{
		strcat(linea, "\"");
		strcat(linea, tabla_procesos->proceso[i].indice_recurso[0]);
		strcat(linea, "\"");
		for (j=1; j< tabla_procesos->proceso[i].cant_pedidos; j++)
		{
			strcat(linea, ", \"");
			strcat(linea, tabla_procesos->proceso[i].indice_recurso[j]);
			strcat(linea, "\"");
		}
			
	}
	else
		strcat(linea, "ninguno");
	return 1;	
}



int statProcesos(RegProcesos *tabla_procesos) 
{
	struct RegProc *r;
	int i = 0;
	struct tm date;
	printf("\n			PROCESOS INICIADOS\n");
	printf("Clave\tNombre\t\tFecha Inicio\tHora Inicio\tDescripcion\n");
	while (i != tabla_procesos->tope) {
		if (tabla_procesos->proceso[i].corriendo) {
			r=&(tabla_procesos->proceso[i]);
			localtime_r(&r->fecha_ejecucion,&date);
			printf("%s\t%s",r->clave,ObtenerNomBin(r->ruta));
			
			printf("\t%d/%d/%d", date.tm_wday,date.tm_mon,1900+date.tm_year);
									
			printf("\t%d:%d:%d\t\t%s\n", date.tm_hour,date.tm_min,date.tm_sec,
										r->descripcion);
		}
		i++;
	}
	
	return 1;	
}

// solo para debug 
int imprimirProcesos(RegProcesos *tabla_procesos)
{
	struct RegProc *r;
	int i = 0;
	struct tm date;
	printf("Clave\tNombre\tFecha Inicio\tHora Inicio\tCORRIENDO\tDescripcion\n");
	while (i != tabla_procesos->tope) {
		r=&(tabla_procesos->proceso[i]);
		localtime_r(&(r->fecha_ejecucion),&date);
		printf("%s\t%s",r->clave,ObtenerNomBin(r->ruta));
		printf("\t%d/%d/%d", date.tm_wday,date.tm_mon,1900+date.tm_year);
		printf("\t%d:%d:%d\t\t%d\t%s\n", date.tm_hour,date.tm_min,date.tm_sec,
									r->corriendo, r->descripcion);

		i++;
	}
	return 1;
}

#endif
