#ifndef TABLE_HPP
#define TABLE_HPP

#include <iostream>
#include <fstream>
#include <string>
#include <stdio.h>
using namespace std;

typedef unsigned int Value;
static const unsigned int SENTINEL = -1;

class Table {
    private:
        int sentinel;
        Value *values;

    public:
        string fileName;
        unsigned int width;
        unsigned int height;
        fstream file;

        Table (string fileName, unsigned int width, unsigned int height): sentinel(-1), fileName(fileName), width(width), height(height) {
            file.open(fileName.c_str(), ios::out | ios::in | ios::binary);
            Value v = 0;
            for (unsigned int i = 0; i < width * height; i++) {
                writeHere(v);
            }
            file.flush();
            values = new Value[width];
        }

        ~Table () {
            delete[] values;
        }

        void moveTo (unsigned int col, unsigned int line) {
            if (col == SENTINEL) {
                sentinel = line;
            }
            else {
                sentinel = -1;
                file.seekp((col * width + line) * sizeof(Value));
            }
        }

        void write (Value v, unsigned int col, unsigned int line) {
            moveTo(col, line);
            writeHere(v);
        }

        void writeHere(Value v) {
            if (sentinel >= 0)
                values[sentinel] = v;
            else
                file.write(reinterpret_cast<const char*>(&v), sizeof(Value));
        }

        
        Value read (unsigned int col, unsigned int line) {
            moveTo(col, line);
            return readHere();
        }

        Value readHere () {
            if (sentinel >= 0) {
                return values[sentinel];
            }
            else {
                Value v;
                file.read(reinterpret_cast<char*>(&v), sizeof(Value));
                return v;
            }
        }

        void destroy () {
            file.close();
            remove(fileName.c_str());
        }

};

#endif
