#define F_CPU 8'000'000UL

#include <stdint.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <avr/io.h>
#include <util/delay.h>


void uart_start() {
    UCSRA = 0b00000000;
    UCSRB = 0b00011000;
    UCSRC = 0b00000110;
    UBRRL = 51; // baud_rate = 9600
    UBRRH = 0;
}

void uart_stop() {
    UCSRB = 0b00000000;
}

bool uart_read(uint8_t *data) {
    uint8_t status, res;
    while(!(UCSRA & (1 << RXC)));

    status = UCSRA;
    res = UDR;

    if(status & ((1 << FE) | (1 << DOR) | (1 << UPE)))
        return false;

    *data = res;
    return true;
}

void uart_write(uint8_t data) {
    while(!(UCSRA & (1 << UDRE)));
    UDR = data;
}

char hostname[8];
char buffer[20];

typedef enum {
    UNPRIVILEGED,
    PRIVILEGED,
    CONFIG
} mode_t;

int main() {
    // Leds
    // DDRB = 0xff;
    // PORTB = 0x00;

    // Buttons
    // DDRD = 0x01;
    // PORTD = 0x01;

    strcpy(hostname, "Router");

    uart_start();

    uint8_t data;
    mode_t mode = UNPRIVILEGED;
    while(true) {
        uart_write('\r');
        uart_write('\n');
        for(uint8_t i=0; i<strlen(hostname); i++) {
            uart_write(hostname[i]);
        }

        switch(mode) {
            case UNPRIVILEGED:
                uart_write('>');
                break;
            case PRIVILEGED:
                uart_write('#');
                break;
            case CONFIG:
                uart_write('(');
                uart_write('c');
                uart_write('o');
                uart_write('n');
                uart_write('f');
                uart_write('i');
                uart_write('g');
                uart_write(')');
                uart_write('#');
                break;
        }
        uint8_t i;
        for(i=0; i<19; i++) {
            if(!uart_read(&data))
                while(true);
            if(data == '\n' || data == '\r')
                break;
            buffer[i] = data;
        }
        buffer[i] = '\0';

        if(strncmp(buffer, "enable", 6) == 0) {
            mode = PRIVILEGED;
        }
        else if(strncmp(buffer, "configure terminal", 18) == 0) {
            mode = CONFIG;
        }
        else if(strncmp(buffer, "hostname", 8) == 0) {
            if(mode == CONFIG) {
                char *ptr = buffer + 8;
                while(true) {
                    if(*ptr == '\0')
                        goto _end;
                    if(!isspace(*ptr)) {
                        break;
                    }
                    ++ptr;
                }

                uint8_t i;
                for(i=0;; i++) {
                    if(*ptr == '\0' || isspace(*ptr))
                        break;
                    hostname[i] = *ptr;
                    ++ptr;
                }
                hostname[i] = '\0';
                _end:;
            }
        }
        else if(strncmp(buffer, "exit", 4) == 0) {
            switch(mode) {
                case UNPRIVILEGED:
                    break;
                case PRIVILEGED:
                    mode = UNPRIVILEGED;
                    break;
                case CONFIG:
                    mode = PRIVILEGED;
                    break;
            }
        }
    }
}
