#include <stdio.h>
#include <stdlib.h>
int minimo,maximo;
typedef struct _fila{
	//Vetor dinamico
	int *vetor;
	//variavel que guarda o tamnho atual do vetor
	int tamanho;
	//guarda a proxima posicao a ser removida
	int remover;
	//guarda a proxima posicao a ser inserida 
	int inserir;
	//guarda o numero de elementos do vetor
	int n_elementos;
}fila;
void criar(fila *f,int tamanho){
	f->vetor=(int*)malloc(sizeof(int)*tamanho);
	f->tamanho=tamanho;
	f->remover=f->inserir=f->n_elementos=0;
}
void destruir(fila *f){
	free(f->vetor);
}
int vazia(fila *f){
	return f->n_elementos==0;
}
int remover(fila *f,FILE *saida,char string[]){
    if (vazia(f)){
		printf("\nTentativa de retirada invalida do buffer %s, pois esta vazio\n",string);
		return 0;
	}
	fprintf(saida,"%d\n",f->vetor[f->remover]);
	printf("\nO valor %d foi removido\n",f->vetor[f->remover]);
	f->remover++;
	f->n_elementos--;
	if (f->remover==f->tamanho)
		f->remover=0;
	if (f->n_elementos<(f->tamanho/3)){
           int *tmp=f->vetor;
		   int i;
		   f->tamanho/=2;
		   f->vetor=(int *)malloc(sizeof(int)*f->tamanho);
		   for (i=0;i<f->n_elementos;i++)
			   f->vetor[i]=tmp[(i+f->remover)%(f->tamanho*2)];
	       free(tmp);
	       f->remover=0;
	       f->inserir=f->n_elementos;
	       printf("\nBuffer %s reduzido pela metade por subutilizacao\n",string);
	     }
	return 1;
}
int inserir(fila *f,int valor,char string[]){
    if (f->n_elementos==f->tamanho){
		if (!(f->tamanho*2>maximo)){
           int *tmp=f->vetor;
		   int i;
		   f->tamanho*=2;
		   f->vetor=(int *)malloc(sizeof(int)*f->tamanho);
		   for (i=0;i<f->n_elementos;i++)
			   f->vetor[i]=tmp[(i+f->remover)%f->tamanho];
	       free(tmp);
	       f->remover=0;
	       f->inserir=f->n_elementos;
	       printf("\nBuffer %s duplicado\n",string);
	     }
	     else{
               printf("\nO valor %d foi descartado devido ao limite do buffer %s ter sido estourado\n",valor,string);
               return 0;
         }
      }
	   f->vetor[f->inserir]=valor;
	   printf("\nO valor %d foi inserido\n",valor);
	   f->inserir=(f->inserir==(f->tamanho-1))?(0):(f->inserir+1);
	   f->n_elementos++;
	   return 1;
}
		
int main(int argc,char **argv){
	if (argc!=4){
		printf("\nDigite na linha de comando o nome do arquivo de entrada e o tamanho minimo e maximo do buffer\n");
		exit(0);
	}
	int numero;
	minimo=atoi(argv[2]);
	maximo=atoi(argv[3]);
	fila fila_positivo,fila_negativo;
	FILE *entrada,*saida_pos,*saida_neg;
	if (!(entrada=fopen(argv[1],"r"))){
                                     printf("\nO arquivo indicado nao pode ser aberto\n");
                                     exit(0);
                                     }
	saida_pos=fopen("positivo.out","w");
	saida_neg=fopen("negativo.out","w");
    criar(&fila_positivo,minimo);
	criar(&fila_negativo,minimo);
	while ((fscanf(entrada,"%d",&numero))!=EOF){
          if (numero>=0){
                         if(inserir(&fila_positivo,numero,"positivo"))
                                                                      remover(&fila_negativo,saida_neg,"negativo");
          }
          else{
                        if(inserir(&fila_negativo,numero,"negativo"))
                                                                     remover(&fila_positivo,saida_pos,"positivo");
          }
    }
	return 0;
}
