import StringUtils from '../../common/StringUtils';
import StringBuilder from '../../util/StringBuilder';
import HighLevelEncoder from './HighLevelEncoder';
import { BASE256_ENCODATION, ASCII_ENCODATION } from './constants';
export class Base256Encoder {
    getEncodingMode() {
        return BASE256_ENCODATION;
    }
    encode(context) {
        const buffer = new StringBuilder();
        buffer.append(0o0); // Initialize length field
        while (context.hasMoreCharacters()) {
            const c = context.getCurrentChar();
            buffer.append(c);
            context.pos++;
            const newMode = HighLevelEncoder.lookAheadTest(context.getMessage(), context.pos, this.getEncodingMode());
            if (newMode !== this.getEncodingMode()) {
                // Return to ASCII encodation, which will actually handle latch to new mode
                context.signalEncoderChange(ASCII_ENCODATION);
                break;
            }
        }
        const dataCount = buffer.length() - 1;
        const lengthFieldSize = 1;
        const currentSize = context.getCodewordCount() + dataCount + lengthFieldSize;
        context.updateSymbolInfo(currentSize);
        const mustPad = context.getSymbolInfo().getDataCapacity() - currentSize > 0;
        if (context.hasMoreCharacters() || mustPad) {
            if (dataCount <= 249) {
                buffer.setCharAt(0, StringUtils.getCharAt(dataCount));
            }
            else if (dataCount <= 1555) {
                buffer.setCharAt(0, StringUtils.getCharAt(Math.floor(dataCount / 250) + 249));
                buffer.insert(1, StringUtils.getCharAt(dataCount % 250));
            }
            else {
                throw new Error('Message length not in valid ranges: ' + dataCount);
            }
        }
        for (let i = 0, c = buffer.length(); i < c; i++) {
            context.writeCodeword(this.randomize255State(buffer.charAt(i).charCodeAt(0), context.getCodewordCount() + 1));
        }
    }
    randomize255State(ch, codewordPosition) {
        const pseudoRandom = ((149 * codewordPosition) % 255) + 1;
        const tempVariable = ch + pseudoRandom;
        if (tempVariable <= 255) {
            return tempVariable;
        }
        else {
            return tempVariable - 256;
        }
    }
}
