// Just look at the function signatures in chernobyl.h and chernobyl_stdlib.h
#include "chernobyl.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "chernobyl_stdlib.h"
#include "chernobyl_types.h"

u16 to_decimal (char *buf) {
   u16 num = 0; // r10
   while (*buf) {
      num *= 10;
      num += *buf - '0';
      buf++;
   }
   return num;
}

int main (int argc, char **argv) {
   if (argc == 1) {
      char buf[0x600] = {0};
      while (printf (">> "), _getsn (buf, 0x5ff), !feof (stdin)) {
         printf ("hash: %x, dec: %x\n", hash (buf), to_decimal (buf));
      };
   }

   if (argc == 2) {
      printf ("hash: %x\n", hash (argv[1]));
   }
   return 0;
}

u16 _main () {
   run ();
   return 0;
}

u16 walk (u16 r15) {
   puts (s_4566);   // "\n\n"
   printf (s_4569); //%x [alloc] [p %x] [n %x] [s %x]
   return 0;
}

// 0x4b66: run
u16 run () {
   // move stack -0x600
   char buf[0x600];
   u16 *hashtable = create_hash_table (0x3, 0x5); // todo: What do these args mean?

   // 4b82: Print out some shit
   puts (s_4a38); // "Welcome to the lock controller."
   puts (s_4a58); // "You can open the door by entering 'access [your name] [pin]'"
   puts (s_4a95); // ""

   while (1) {
      // 4b9a: zero out the stack buffer
      for (int r14 = 0; r14 < 0x5ff; r14++) {
         buf[r14] = 0;
      }
      // 4bb0: get 0x550 characters -> stack buffer
      _getsn (buf, 0x550);
      // 4bba: loop over the user input:
      u16 index = 0;
      while (buf[index] != 0) {
         // 4bbe: check for 'a'
         if (buf[index] == 'a') {
            index += 7;
            char *name = &buf[index];
            // skip spaces
            while (buf[index++] != ' ') {
               if (buf[index] == 0)
                  break;
            };
         } else if (buf[index] == 'n') {
            index += 4;
            // skip spaces
            while (buf[index++] != ' ') {
               if (buf[index] == 0)
                  break;
            };
         } else {
            return -1;
         }
      }
   }
   // end of the function
   puts (s_4b54); // "Invalid command."
   return 1;
}

u16 *create_hash_table (u16 r15, u16 r14) {
   // todo: RE hash table creation
   u8 *buf = (u8 *) malloc (0xa);
   buf[0]  = 0;
   return 0;
}

// Hash the string stored at addr
u16 hash (char *addr) {
   u16 chr, hash = 0;
   while (*addr) {
      hash = *addr + hash;
      hash = (hash << 5) - hash;
      addr++;
   }
   return hash;
}

u16 add_to_table (u16 *table, char *username, u16 pin) {
   // todo: add_to_table
   u16 r14 = table[1]; // Box bitmask exponent? 3
   u16 r12 = table[2]; // Box bitmask mantissa? 5
   //! What the hell is going on here?
   r12 <<= r14; // 3 <<= 5
   if (r12 < 0) {
      r12 = r12 + 3;
   }
   r12 >>= 2;
   if (table[0] < r12) {    // if there are more names in table than 10:
      rehash (*table, r14); // Make more boxes, and shuffle them around?
   }
   table[0]++;
   hash (r14);
   r12 = 1 << table[1];
   // Then do some boring stuff
   return 0;
}

// get_from_table hash_table* table, string* username
u16 get_from_table (void *r15, char *r14) {
   u16 h            = hash (r14);
   u16 num          = ((u16 *) r15)[2];
   u16 power_of_two = (1 << num) - 1;
   power_of_two     = (power_of_two & h) << 1;
   num              = ((u16 *) r15)[6];

   return 0;
}

u16 rehash (u16 *table, u16 exponent) { // Now I see the problem
   // This function makes the hash table 2^exponent units long
   // and rehashes all the usernames stored in each box
   return 0;
}
