global _start


section .data

; Texte et message à afficher dans la sortie standard
mainPrompt: db "> "
mainPromptLength: equ $-mainPrompt
secondaryPrompt: db ": "
secondaryPromptLength: equ $-secondaryPrompt
welcomeMessage: db "COMPUTER ARCHITECTURE PROJET: REGISTRATION PROGRAM", 10, "Press 'h' or return key for a list of the available commands.", 10
welcomeMessageLength: equ $-welcomeMessage
helpMessage: db "Available commands:", 10, " r - Register a new person", 10, " l - Lists all registered persons", 10, " s - Search and display a specific person", 10, " y - Display the youngest person registered", 10, " q - Quit the program", 10
helpMessageLength: equ $-helpMessage
commandErrorMessage: db "ERROR: Unknown command.", 10, 7
commandErrorMessageLength: equ $-commandErrorMessage
fileErrorMessage: db "ERROR: No registry file, please create one.", 10, 7
fileErrorMessageLength: equ $-fileErrorMessage
numberErrorMessage: db "ERROR: Not a number.", 10, 7
numberErrorMessageLength: equ $-numberErrorMessage
searchErrorMessage: db "ERROR: Requested person not found.", 10, 7
searchErrorMessageLength: equ $-searchErrorMessage
space: db ' '
spaceLength: equ $-space
comma: db ','
commaLength: equ $-comma

; Fichier
fileName: db "registry.csv"
fd : dw 0

; Mémoire tampon
mainPromptBuffer: db 2 dup(0)
secondaryPromptBuffer: db 1024 dup(0)
generalPurposeBuffer: db 8192 dup(0)
numberBuffer: db 12


section .text

_start:
    ; Message informatif au démarrage du programme
    mov eax, 4
    mov ebx, 1
    mov ecx, welcomeMessage
    mov edx, welcomeMessageLength
    int 80h

    ; Gestion de l'invite de commande principal
    .prompt:
        ; Affichage de l'invite de commande
        mov eax, 4
        mov ebx, 1
        mov ecx, mainPrompt
        mov edx, mainPromptLength
        int 80h
        ; Lecture de la commande entrée par l'utilisateur
        mov eax, 3
        mov ebx, 0
        mov ecx, mainPromptBuffer
        mov edx, 2
        int 80h
        ; Gestion des différentes opération du programme selon la commande reçue
        cmp eax, 0
        jle .error
        cmp byte [mainPromptBuffer], 10 ; Affiche l'aide si l'on appuie sur la touche retour
        je .help
        cmp byte [mainPromptBuffer + 1], 10
        jne .flush
        cmp byte [mainPromptBuffer], "h"
        je .help
        cmp byte [mainPromptBuffer], "r"
        je .register
        cmp byte [mainPromptBuffer], "l"
        je .list
        cmp byte [mainPromptBuffer], "s"
        je .search
        cmp byte [mainPromptBuffer], "y"
        je .youngest
        cmp byte [mainPromptBuffer], "q"
        je .quit
        jmp .error

        .help:
            mov eax, 4
            mov ebx, 1
            mov ecx, helpMessage
            mov edx, helpMessageLength
            int 80h
            jmp .prompt

        .register:
            call register
            jmp .prompt

        .list:
            call list
            jmp .prompt

        .search:
            call search
            jmp .prompt

        .youngest:
            call youngest
            jmp .prompt

        .flush:
            mov eax, 3
            mov ebx, 0
            mov ecx, mainPromptBuffer
            mov edx, 1
            int 80h
            cmp byte [mainPromptBuffer], 10
            jne .flush
            jmp .error

        .error:
            ; Affichage d'un message d'erreur
            mov eax, 4
            mov ebx, 2
            mov ecx, commandErrorMessage
            mov edx, commandErrorMessageLength
            int 80h
            jmp .prompt

    ; Quitte le programme avec le valeur 0 (Succès)
    .quit:
        mov eax, 1
        xor ebx, ebx
        int 80h

register:
    ; Ouverture du fichier en lecture seule
    mov eax, 5
    mov ebx, fileName
    xor ecx, ecx
    mov edx, 0666o
    int 80h
    mov edi, 1
    cmp eax, 0
    jl .create

    mov esi, eax

    ; Calcul du nombre de lignes du fichier
    .while:
        mov eax, 3
        mov ebx, esi
        mov ecx, generalPurposeBuffer
        mov edx, 1
        int 80h
        cmp eax, 0
        je .end_while
        cmp byte [generalPurposeBuffer], 10
        je .inc
        jmp .while

    .inc:
        inc edi
        jmp .while

    .end_while:

    ; Fermeture du fichier ouvert en lecture
    mov eax, 6
    mov ebx, esi
    int 80h

    ; Conversion de l'entier en chaîne de caractères
    mov eax, edi
    mov esi, numberBuffer
    mov byte [esi], 0
    mov ebx, 10
    xor ecx, ecx

    .convert:
        xor edx, edx
        div ebx
        add dl, 48
        dec esi
        mov [esi], dl
        inc ecx
        cmp eax, 0
        jne .convert

    mov edi, esi

    ; Affichage de l'invite de commande secondaire
    .open:
    push edi
    push ecx
    mov eax, 4
    mov ebx, 1
    mov ecx, secondaryPrompt
    mov edx, secondaryPromptLength
    int 80h

    ; Ouverture du fichier en écriture
    mov eax, 5
    mov ebx, fileName
    mov ecx, 401h
    mov edx, 0666o
    int 80h

    ;cmp eax, 0
    ;jbe .create

    mov esi, eax

    mov eax, 4
    mov ebx, esi
    pop ecx
    mov edx, ecx
    pop edi
    mov ecx, edi
    int 80h

    mov eax, 4
    mov ebx, esi
    mov ecx, comma
    mov edx, commaLength
    int 80h

    .write:
        mov eax, 3
        xor ebx, ebx
        mov ecx, secondaryPromptBuffer
        mov edx, 1
        int 80h

        mov edx, eax

        mov eax, 4
        mov ebx, esi
        cmp byte [secondaryPromptBuffer], ' '
        je .comma
        jmp .skip
        .comma:
            mov ecx, comma
            jmp .interrupt
        .skip:
            mov ecx, secondaryPromptBuffer
        .interrupt:
        int 80h
        cmp byte [secondaryPromptBuffer], 10
        je .end
        jmp .write

    .create:
        mov eax, 5
        mov ebx, fileName
        mov ecx, 100o
        mov edx, 0666o
        int 80h
        ; Fermeture du fichier
        mov ebx, eax
        mov eax, 6
        int 80h
        jmp register

    .end:
        ; Fermeture du fichier
        mov eax, 6
        mov ebx, esi
        int 80h
        ret

list:
    ; Ouverture du fichier regristry.csv
    mov eax, 5
    mov ebx, fileName
    xor ecx, ecx
    mov edx, 0666o
    int 80h
    cmp eax, -2 ; Affiche une erreur si le fichier n'existe pas
    je .error

    mov esi, eax ; Copie du descripteur de fichier dans esi

    ; Affichage de la liste
    .loop:
        mov eax, 3
        mov ebx, esi
        mov ecx, generalPurposeBuffer
        mov edx, 1
        int 80h
        cmp eax, 0
        jbe .end
        mov edx, eax
        mov eax, 4
        mov ebx, 1
        cmp byte [generalPurposeBuffer], ','
        jne .nocomma
        mov ecx, space
        jmp .interrupt
        .nocomma:
            mov ecx, generalPurposeBuffer
        .interrupt:
        int 80h
        jmp .loop

    .error:
        mov eax, 4
        mov ebx, 2
        mov ecx, fileErrorMessage
        mov edx, fileErrorMessageLength
        int 80h
        ret

    .end:
        ; Fermeture du fichier
        mov eax, 6
        mov ebx, esi
        int 80h
        ret

search:
    ; Affichage de l'invite de commande secondaire
    mov eax, 4
    mov ebx, 1
    mov ecx, secondaryPrompt
    mov edx, secondaryPromptLength
    int 80h

    xor edi, edi

    .convert:
        ; Lecture de l'entrée standard
        mov eax, 3
        xor ebx, ebx
        mov ecx, secondaryPromptBuffer
        mov edx, 1
        int 80h

        ; Conversion en entier
        xor ebx, ebx
        mov bl, [secondaryPromptBuffer]
        cmp ebx, 10
        je .print

        sub ebx, 48
        imul edi, 10
        add edi, ebx
        jmp .convert

    .print:
    ; Ouverture du fichier regristry.csv
    mov eax, 5
    mov ebx, fileName
    xor ecx, ecx
    mov edx, 0666o
    int 80h
    cmp eax, -2 ; Affiche une erreur si le fichier n'existe pas
    je .error

    mov esi, eax ; Copie du descripteur de fichier dans esi

    cmp edi, 1 ; Dans le cas où edi = 1, on passe la boucle
    je .loop

    .while:
        mov eax, 3
        mov ebx, esi
        mov ecx, generalPurposeBuffer
        mov edx, 1
        int 80h
        cmp eax, 0
        je .end
        cmp byte [generalPurposeBuffer], 10
        je .dec
        .next:
            cmp edi, 1
            je .loop
        jmp .while

    ; Affichage de la ligne
    .loop:
        mov eax, 3
        mov ebx, esi
        mov ecx, generalPurposeBuffer
        mov edx, 1
        int 80h
        cmp eax, 0
        jbe .unknown
        mov edx, eax
        mov eax, 4
        mov ebx, 1
        cmp byte [generalPurposeBuffer], ','
        jne .nocomma
        mov ecx, space
        jmp .interrupt
        .nocomma:
            mov ecx, generalPurposeBuffer
        .interrupt:
        int 80h
        cmp byte [generalPurposeBuffer], 10
        je .end
        jmp .loop

    .error:
        mov eax, 4
        mov ebx, 2
        mov ecx, fileErrorMessage
        mov edx, fileErrorMessageLength
        int 80h
        ret

    .unknown:
        mov eax, 4
        mov ebx, 2
        mov ecx, searchErrorMessage
        mov edx, searchErrorMessageLength
        int 80h
        ret

    .end:
        ; Fermeture du fichier
        mov eax, 6
        mov ebx, esi
        int 80h
        ret

    .dec:
        dec edi
        jmp .next

youngest:
    ; Ouverture du fichier regristry.csv
    mov eax, 5
    mov ebx, fileName
    xor ecx, ecx
    mov edx, 0666o
    int 80h
    cmp eax, -2 ; Affiche une erreur si le fichier n'existe pas
    je .error

    mov esi, eax

    xor eax, eax
    push eax
    push eax
    mov eax, 65536
    push eax

    .get_ages:

    mov edi, 2

    .get_to_age:
        mov eax, 3
        mov ebx, esi
        mov ecx, generalPurposeBuffer
        mov edx, 1
        int 80h

        cmp eax, 0
        jbe .print

        cmp byte [generalPurposeBuffer], ','
        je .dec_comma
        .dec_comma_ret:
        cmp edi, 0
        jne .get_to_age

    .convert:
        mov eax, 3
        mov ebx, esi
        mov ecx, generalPurposeBuffer
        mov edx, 1
        int 80h

        cmp eax, 0
        jbe .print

        ; Conversion en entier
        xor ebx, ebx
        mov bl, [generalPurposeBuffer]
        cmp ebx, 10
        je .newline

        sub ebx, 48
        imul edi, 10
        add edi, ebx
        jmp .convert


    .newline:
        pop eax
        cmp eax, edi
        pop ebx
        inc ebx
        jbe .not_younger
        pop ecx
        mov ecx, ebx
        push ebx
        push ebx
        push edi
        jmp .get_ages
        .not_younger:
            push ebx
            push eax
            jmp .get_ages

    .print:
    pop eax
    pop edi
    pop edi

    cmp edi, 1 ; Dans le cas où edi = 1, on passe la boucle
    je .loop

    ; Fermeture du fichier
    mov eax, 6
    mov ebx, esi
    int 80h
    ; Ouverture du fichier regristry.csv
    mov eax, 5
    mov ebx, fileName
    xor ecx, ecx
    mov edx, 0666o
    int 80h
    cmp eax, -2 ; Affiche une erreur si le fichier n'existe pas
    je .error

    mov esi, eax ; Copie du descripteur de fichier dans esi

    .while:
        mov eax, 3
        mov ebx, esi
        mov ecx, generalPurposeBuffer
        mov edx, 1
        int 80h
        cmp eax, 0
        je .end
        cmp byte [generalPurposeBuffer], 10
        je .dec
        .next:
            cmp edi, 1
            je .loop
        jmp .while

    ; Affichage de la ligne
    .loop:
        mov eax, 3
        mov ebx, esi
        mov ecx, generalPurposeBuffer
        mov edx, 1
        int 80h
        cmp eax, 0
        jbe .unknown
        mov edx, eax
        mov eax, 4
        mov ebx, 1
        cmp byte [generalPurposeBuffer], ','
        jne .nocomma
        mov ecx, space
        jmp .interrupt
        .nocomma:
            mov ecx, generalPurposeBuffer
        .interrupt:
        int 80h
        cmp byte [generalPurposeBuffer], 10
        je .end
        jmp .loop

    .error:
        mov eax, 4
        mov ebx, 2
        mov ecx, fileErrorMessage
        mov edx, fileErrorMessageLength
        int 80h
        ret

    .unknown:
        mov eax, 4
        mov ebx, 2
        mov ecx, searchErrorMessage
        mov edx, searchErrorMessageLength
        int 80h
        ret

    .end:
        ; Fermeture du fichier
        mov eax, 6
        mov ebx, esi
        int 80h
        ret

    .dec:
        dec edi
        jmp .next

    .dec_comma:
        dec edi
        jmp .dec_comma_ret
