#include <stdio.h>
#include <conio.h>
#include <process.h>
#include <string.h>
#include <ctype.h>
#include <dir.h>
#include <io.h>

struct client
{
 int codi,edat;
 char nom[30],cog1[30],cog2[30];
 char sexe;
 char verge; /* Els registres verges tindran aquest camp a 'S' */
};

int numreg_fr(FILE *f, char tipus)
{
 /* tipus pot ser 'O' (ocupats) 'V' (verges) 'T' (totals)
	 i la funcio tornara quans registres d'aquest tipus n'hi han
	 al fitxer */
 int n,ocupats,verges;
 fpos_t p;
 struct client r;
 n=0;
 ocupats=0;
 verges=0;
 fgetpos(f,&p);
 fseek(f,0L,SEEK_SET);
 fread(&r,sizeof(struct client),1,f);
 while (!feof(f))
 {
  if (r.verge=='S') verges++;
  else ocupats++;
  fread(&r,sizeof(struct client),1,f);
 }
 if (tipus=='T') n=ocupats+verges;
 else if(tipus=='O') n=ocupats;
 else n=verges;
 fsetpos(f,&p);
 return n;
}

void llegir_seq_fr(FILE *f, struct client *r)
{
 /* La funcio llegira el seguent registre fins trobar-ne un d'ocupat,
	 o fins trobar el final de l'arxiu. No torna cap valor directe,
	 pero si torna el registre llegit, que hem passat per referencia */
 fread(r,sizeof(struct client),1,f);
 while (!feof(f) && r->verge=='S') fread(r,sizeof(struct client),1,f);
}

int llegir_dir_fr(FILE *f, struct client *r, int pos)
{
 /* La funcio ha de tornar en la variable r, passada per referencia, el
	 registre que ocupa la posicio pos. En cas de realitzar l'operacio
	 correctament, retornara un 0; si el registre es verge, tornara 1; i
	 si el registre no existeix, tornara un -1 */
 int resultat;
 int x;
 x=0;
 if(pos > numreg_fr(f,'T')) resultat=-1;
 else
 {
  x=fseek(f,(pos-1)*(sizeof(struct client)),SEEK_SET);
  x=fread(r,sizeof(struct client),1,f);
  if (r->verge=='S') resultat=1;
  else resultat=0;
 }
 return resultat;
}

int escriure_fr(FILE *f, struct client r, int pos)
{
/* La funcio ha d'escriure el registre r en la posicio pos.
	En cas de realitzar l'operacio correctament, retornara un 0; si el
	registre no es verge, tornara 1; i si el registre no existeix,
	tornara un -1 */

 int resultat;
 int x;
 fpos_t p;
 struct client r1;
 if(pos > numreg_fr(f,'T')) resultat=-1;
 else
 {
  x=fseek(f,(pos-1)*sizeof(struct client),SEEK_SET);
  x=fgetpos(f,&p);
  x=fread(&r1,sizeof(struct client),1,f);
  if (r1.verge=='N') resultat=1;
  else
	{
	  x=fsetpos(f,&p);
	  x=fwrite(&r,sizeof(struct client),1,f);
	  resultat=0;
	}
  }
  return resultat;
}

int esborrar_fr(FILE *f)
{
 /* Hauriem d'estar posicionats abans del registre que volem esborrar */
 int x;
 fpos_t p;
 struct client r;
 /* Com representa que haurem fet abans un llegir_dir_fr, el punter estara
	 despres del registre, l'hem de deixar abans del registre*/
 fseek(f,-(long)sizeof(struct client),SEEK_CUR);
 fgetpos(f,&p);
 llegir_seq_fr(f,&r);
 r.verge='S';
 fsetpos(f,&p);
 x=fwrite(&r,sizeof(struct client),1,f);
}

void estendre_fr(FILE *f, int num)
{
 int k;
 struct client r;
 fseek(f,0L,SEEK_END);
 r.codi=0;r.edat=0;
 r.nom[0]='\0';r.cog1[0]='\0';r.cog2[0]='\0';
 r.sexe=' ';r.verge='S';
 for (k=1;k<=num;k++) fwrite(&r,sizeof(struct client),1,f);
}

void entradades(struct client *r)
{
 clrscr();
 printf("\nCodi.........: %d ",r->codi);
 fflush(stdin);
 printf("\nNom..........: ");scanf("%s",r->nom);fflush(stdin);
 printf("\n1er Cognom...: ");scanf("%s",r->cog1);fflush(stdin);
 printf("\n2on Cognom...: ");scanf("%s",r->cog2);fflush(stdin);
 printf("\nEdat.........: ");scanf("%d",&(r->edat));fflush(stdin);
 do
  {
	printf("\nSexe.........: ");scanf("%c",&(r->sexe));fflush(stdin);
  }
 while (r->sexe != 'H' && r->sexe != 'D');
 printf("\n\nPremi una tecla");getch();
}


void main()
{
 FILE *f,*f1,*f2;
 struct client r,r1,r2;
 char siono;
 int comptador,comptador2,op,op2,x,x1,x2,codcli;
 f=fopen("CLIENTS.DAT","r+b");
 if (f==NULL) f=fopen("CLIENTS.DAT","wb");
 do
 {
	clrscr();
	printf("\n *** MANTENIMIENT DE CLIENTS *** \n\n");
	printf("\n 1 - Introduccio d'un client. ");
	printf("\n 2 - Baixa d'un client.");
	printf("\n 3 - Modificacio d'un client.");
	printf("\n 4 - Llistar els clients.");
	printf("\n 5 - Sortir del programa.");
	printf("\n\nIntroduiu opcio: ");
	do scanf("%d",&op); while (op < 1 || op > 5);
	switch (op)
	{
	 case 1:
		clrscr();
		printf("Introduieixi el codi: ");scanf("%d",&(r.codi));
		x=llegir_dir_fr(f, &r1, r.codi);
		if (x==0) printf("\n\nAquest codi ja existeix.");
		else
		 {
			if(x==-1)
			  {
				printf("S'ha de fer un estendre.");getch();
				estendre_fr(f,(r.codi - numreg_fr(f,'T')));
			  }
			printf("Codi: %d ",r.codi);
			entradades(&r);
			x=escriure_fr(f,r,r.codi);
			if (x==0)
				 printf("\n\nOperacio realitzada. Premi una tecla.");
			else
				 printf("\n\nProblemes amb l'escriure.Error %d .Premi una tecla.",x);
			fclose(f);
			f=fopen("CLIENTS.DAT","r+b");
		 }
		getch();
		break;
	 case 2:
		codcli=0;
		printf("Client que vol donar de baixa: ");scanf("%d",&codcli);fflush(stdin);
		printf("\n");
		x=llegir_dir_fr(f,&r,codcli);
		if (x!=0) printf("El client no existeix.");
		else
		{
		 esborrar_fr(f);
		 printf("\n\nOperacio realitzada. Premi una tecla.");
		 fclose(f);
		 f=fopen("CLIENTS.DAT","r+b");
		}
		getch();
		break;
	 case 3:
		printf("\nClient que vol modificar: ");scanf("%d",&codcli);fflush(stdin);
		printf("\n");
		x=llegir_dir_fr(f,&r,codcli);
		if (x != 0) printf("El client no existeix");
		else
		{
		 entradades(&r);
		 fseek(f,-(long)(sizeof(struct client)),SEEK_CUR);
		 x=fwrite(&r,sizeof(struct client),1,f);
		 printf("\n\nOperacio realitzada. Premi una tecla.");
		 fclose(f);
		 f=fopen("CLIENTS.DAT","r+b");
		}
		getch();break;
	 case 4:
		printf("\n\nLLISTAT DE CLIENTS\n\n");
		fseek(f,0L,SEEK_SET);
		llegir_seq_fr(f,&r);
		while (!feof(f))
		 {
		  printf("\n %s %s %s %d %c ",r.nom,r.cog1,r.cog2,r.edat,r.sexe);
		  llegir_seq_fr(f,&r);
		 }
		printf("\n\nPremi una tecla.");
		getch();break;
	}
 }
 while (op!=5);
 fclose(f);
}


