#ifndef SPLITSTRING_H
#define SPLITSTRING_H

#include "data/List.h"
#include "utils/StringBuffer.h"

template<int N>
class SplitString final {
    List<int> entries;
    List<char> data;

    bool fill(const StringBuffer<N>& s) {
        for(int i = 0; i < s.getLength(); i++) {
            switch(s[i]) {
                case ' ': handleSpace(s, i); break;
                case '"':
                    if(handleQuotation(s, i)) {
                        return true;
                    }
                    break;
                default: data.add(s[i]);
            }
        }
        data.add('\0');
        return false;
    }

    void handleSpace(const StringBuffer<N>& s, int& i) {
        while(i + 1 < s.getLength() && s[i + 1] == ' ') {
            i++;
        }
        if(i + 1 < s.getLength()) {
            data.add('\0');
        }
    }

    bool handleQuotation(const StringBuffer<N>& s, int& i) {
        if(i != 0 && s[i - 1] != ' ') {
            return true;
        }
        i++;
        while(i < s.getLength() && s[i] != '"') {
            data.add(s[i++]);
        }
        if(i >= s.getLength() || (i != s.getLength() - 1 && s[i + 1] != ' ')) {
            return true;
        }
        return false;
    }

    void addEntries() {
        int lastIndex = 0;
        for(int i = 0; i < data.getLength(); i++) {
            if(data[i] == '\0') {
                entries.add(lastIndex);
                lastIndex = i + 1;
            }
        }
    }

public:
    SplitString(const StringBuffer<N>& s) {
        if(fill(s)) {
            return;
        }
        addEntries();
    }

    int getLength() const {
        return entries.getLength();
    }

    const char* operator[](int index) const {
        return &(data[entries[index]]);
    }
};

#endif