/***********************************************
 *      Author: Alexander Oro Acebo
 *        Date: 01/22/2015
 * Description: Change current dir
 * ********************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/shm.h>
#include "../include/RootDir.h"
#include "../include/fatSupport.h"
#include "../include/Shared_Info.h"

#define BYTES_TO_READ_IN_BOOT_SECTOR 512
#define BLUE  "\x1B[1;36m"					// for listing directories as blue
#define RESET "\033[0m"
#define BOLD  "\033[1m"

FILE* FILE_SYSTEM_ID;
int   BYTES_PER_SECTOR;
char* NEW_DIR;

Shared_Info *CUR_DIR;

void     usage();
char*    readFile(char*, char*[]);
char*	 readFileNonRoot(char*);
void     getSharedMem(int, key_t, char*, char*);
void 	 createSharedMem(int, key_t, char*, char*);
char*    readFAT12Table(char*);

int main(int argc, char *argv[])
{
   int fd[2], nbytes;
   int i = 0, j = 0;
   char *buffer;
   
   int shmid;
   key_t key;
   char *shm, *s, *pch, tmp[9], *tmp_cur;
   
   CUR_DIR = malloc(sizeof(Shared_Info));
   
   // Read shared memory from terminal
   getSharedMem(shmid, key, shm, s);
   
   char *trunk[CUR_DIR->FLC];
   
   if (argc != 2) {
	   usage();
	   return 1;
   }
   
   NEW_DIR = malloc(sizeof(argv));
   strcpy(NEW_DIR, argv[argc - 1]);

   FILE_SYSTEM_ID = fopen(CUR_DIR->img, "r+");

   if (FILE_SYSTEM_ID == NULL)
   {
      fprintf(stderr, "Could not open the floppy drive or image.\n");
      exit(1);
   }

   // Set it to this only to read the boot sector
   BYTES_PER_SECTOR = BYTES_TO_READ_IN_BOOT_SECTOR;
   buffer = (char*) malloc(32 * sizeof(char));

   if (strcmp(NEW_DIR, "..") != 0) {
	   tmp_cur = malloc(sizeof(CUR_DIR->path));
	   strcpy(tmp_cur, CUR_DIR->path);
	   i = 0;
	   pch = strtok(tmp_cur, " /");
	   while (pch != NULL) {
		   trunk[i] = pch;
		   pch = strtok(NULL, " /");
		   i++;
	   }
	   
	   if (strcmp(CUR_DIR->path, "/") == 0)
			buffer = readFile(buffer, trunk);			// Read directory sectors into buffer
	   else
			buffer = readFileNonRoot(buffer);
   } else {
	   tmp_cur = malloc(sizeof(CUR_DIR->path));
	   strcpy(tmp_cur, CUR_DIR->path);
	   
	   pch = strtok(tmp_cur, " /");
	   while (pch != NULL) {
		    strcpy(tmp, pch);
			pch = strtok(NULL, " /");
	   }

	   strcpy(tmp_cur, CUR_DIR->path);
	   strcpy(CUR_DIR->path, "/");
	   pch = strtok(tmp_cur, " /");

	   while (strcmp(pch, tmp) != 0) {
		   strcat(CUR_DIR->path, pch);
		   strcat(CUR_DIR->path, "/");
		   pch = strtok(NULL, " /");
	   }
	   
	   CUR_DIR->FLC = CUR_DIR->OLD_FLC;
   }
   
   // Free data
   free(buffer);
   
   buffer = NULL;
   
   fclose(FILE_SYSTEM_ID);
   
   // Push new shared data to terminal
   createSharedMem(shmid, key, shm, s);

   exit(EXIT_SUCCESS);
}

char* readFAT12Table(char* buffer) {	
	int i = 0;
	
	// Read in FAT table to buffer
   for (i = 1; i <= 9; i++) {
	   if (read_sector(i, (buffer + BYTES_PER_SECTOR * (i - 1))) == -1) {
		  fprintf(stderr, "Something has gone wrong -- could not read the sector\n");
	   }		
   }
   
   return buffer;
}

void createSharedMem(int shmid, key_t key, char * shm, char * s) {
	key = 5678;
	int i = 0;
	Shared_Info* tmp;

	if ((shmid = shmget(key, sizeof(Shared_Info*), IPC_CREAT | 0666)) < 0) {
        perror("shmget");
        exit(1);
    }
    
    if ((tmp = shmat(shmid, NULL, 0)) == (Shared_Info*) -1) {
        perror("shmat");
        exit(1);
    }
    
    tmp = CUR_DIR;
    tmp = NULL;
    //s = shm;
    
    // Write current path to shared memory
    //for (i = 0; i < sizeof(CUR_DIR->path); i++)
    //    *s++ = CUR_DIR->path[i];
    //*s = NULL;
}

void getSharedMem(int shmid, key_t key, char * shm, char * s) {
	key = 5678;
	int i = 0;
	Shared_Info* tmp;
	
	if ((shmid = shmget(key, sizeof(Shared_Info*), 0666)) < 0) {
        perror("shmget");
        exit(1);
    }
    
    if ((tmp = shmat(shmid, NULL, 0)) == (Shared_Info*) -1) {
        perror("shmat");
        exit(1);
    }

	CUR_DIR = tmp;
	//i = 0;
    //for(s = shm; *s != NULL; s++) {
	//	CUR_DIR->path[i] = *s;
	//	i++;
	//}
}

char* readFileNonRoot(char* buffer) {
	int fat, start_sector = CUR_DIR->FLC, i = 0, j = 0, attrib, tmp1, tmp2;
	// Allocate memory
	char *sector = (char*) malloc(BYTES_PER_SECTOR * sizeof(char));
	char *fat_buffer = (char*) malloc(9 * BYTES_PER_SECTOR * sizeof(char));
	char tmp[9];
	
	fat_buffer = readFAT12Table(fat_buffer);	// Read fat table into buffer
	
	while (1) {
		if (read_sector(start_sector, sector) == -1) {	// Read data sector
			fprintf(stderr, "Something has gone wrong -- could not read the boot sector\n");
		}
		
		i = 0;
		j = 0;
		while (i < 512) {
			for (j = 0; j < 32; j++)
				buffer[j] = sector[j + i];
			
			attrib = ( (int) buffer[11] );
		
			// if is subdir
			if (attrib == 16) {
				// read subdir name into tmp
				for (j = 0; j < 8; j++)
					tmp[j] = buffer[j];
					
				tmp[strlen(NEW_DIR)] = '\0';
				NEW_DIR[strlen(NEW_DIR)] = '\0';
				
				// compare
				if (strcmp(NEW_DIR, tmp) == 0) {
					strcat(CUR_DIR->path, NEW_DIR);
					strcat(CUR_DIR->path, "/");
					tmp1 = ( ( (int) buffer[27] ) << 8 ) & 0x0000ff00;
					tmp2 =   ( (int) buffer[26] )        & 0x000000ff;
					CUR_DIR->FLC = tmp1 | tmp2;
					CUR_DIR->FLC += 33 - 2;
					break;
				}
			}
			i += 32;
		}
		
		//printf("\n");
		
		//printf("%s\n", sector);		// Display data sector contents
		fat = get_fat_entry(start_sector - 33 + 2, fat_buffer);		// Get fat entrie from table buffer
		
		if (fat >= 4088 && fat <= 4095) {	// Last cluster in file
			break;
		} else if (fat >= 4080 && fat <= 4086) {	// Reserved cluster
			break;
		} else if (fat == 0 || fat == 4087) {	// Unused OR Bad cluster
			break;
		} else {	// Next cluster in file
			start_sector = fat + 33 - 2;
		}
	}
	
	// Free memory
	free(sector);
	free(buffer);
	
	sector = NULL;
	buffer = NULL;
}

char* readFile(char* buffer, char* trunk[]) {
	int i = 0, j = 0, bytes_read, attrib, tmp1, tmp2;
	char tmp[9];
	fpos_t position;

    i = CUR_DIR->FLC * 512;
    fseek(FILE_SYSTEM_ID, i, SEEK_SET);  // Set pos to beginning file
	while (1) {
		bytes_read = fread(buffer, sizeof(char), 32, FILE_SYSTEM_ID); // read 32 bytes at a time into buffer
		
		attrib = ( (int) buffer[11] );
		
		// if is subdir
		if (attrib == 16) {
			// read subdir name into tmp
			for (j = 0; j < 8; j++)
				tmp[j] = buffer[j];
				
			tmp[strlen(NEW_DIR)] = '\0';
			NEW_DIR[strlen(NEW_DIR)] = '\0';
			
			// compare
			if (strcmp(NEW_DIR, tmp) == 0) {
				strcat(CUR_DIR->path, NEW_DIR);
				strcat(CUR_DIR->path, "/");
				tmp1 = ( ( (int) buffer[27] ) << 8 ) & 0x0000ff00;
				tmp2 =   ( (int) buffer[26] )        & 0x000000ff;
				CUR_DIR->FLC = tmp1 | tmp2;
				CUR_DIR->FLC += 33 - 2;
				break;
			}
		}
			
		if (i >= 32 * 512) { // If i has incrimented to the end of the root dir break
			fprintf(stderr, "ERROR: directory '%s' does not exist\n", NEW_DIR);
			break;
		}
		
		i = i + 32;			
    }
    
    return buffer;
}

void usage() {
	printf("\nusage: cd (/path/to/SUBDIR)\n\n");
}
