function binSearch(list, word) {
    let first = 0;
    let last = list.length;

    for (;;) {
        let ptr = (first + (last - first) / 2) | 0;
        if (list[ptr] === word) {
            return true;
        } else if (last - first <= 1) {
            return false;
        } else if (list[ptr] > word) {
            last = ptr;
        } else if (list[ptr] < word) {
            first = ptr;
        }
    }
}


export class WordSource {
    constructor() {
        this._dataVersion = null;
        this._wordData = null;
        this._otherWords = null;
        this._pattern = null;
    }

    isWord(word) {
        if (!this._wordData || !this._otherWords) {
            return false;
        }

        return binSearch(this._wordData[word.length.toString()], word) ||
            binSearch(this._otherWords[word.length.toString()], word);
    }

    async needToResetProgression(prog) {
        await this._fetchAllWordsIfNecessary();
        return !prog || !prog.shuffleId || this._dataVersion !== prog.shuffleId;
    }

    async getPattenShuffleID() {
        return this._dataVersion;
    }
    
    async getCurrentWord(prog) {
        await this._fetchAllWordsIfNecessary();

        let wordLengthKey = prog.wordLength + "";
        let wordIndex = prog.wordIndex[wordLengthKey];
        let idx = this._pattern[wordLengthKey][wordIndex];

        return this._wordData[wordLengthKey][idx];
    }
    
    async _fetchAllWordsIfNecessary() {
        if (this._wordData) {
            return this._wordData;
        }

        let data = await (await fetch("/assets/data/data.json")).json();

        this._dataVersion = data["versionId"];
        this._wordData = data["guessWords"];
        this._otherWords = data["otherWords"];
        this._pattern = data["shufflePattern"];
    }
}