export class WplaceBitmap {
	private bytes: Uint8Array;

	constructor(base64?: string) {
		if (base64) {
			this.bytes = Uint8Array.from(atob(base64), (c) => c.charCodeAt(0));
		} else {
			this.bytes = new Uint8Array(0);
		}
	}

	get(index: number): boolean {
		const byteIndex = Math.floor(index / 8);
		const bitIndex = index % 8;
		if (byteIndex >= this.bytes.length) return false;
		const realIndex = this.bytes.length - 1 - byteIndex;
		return (this.bytes[realIndex] & (1 << bitIndex)) !== 0;
	}

	set(index: number, value: boolean): void {
		const byteIndex = Math.floor(index / 8);
		const bitIndex = index % 8;

		if (byteIndex >= this.bytes.length) {
			const newBytes = new Uint8Array(byteIndex + 1);
			const offset = newBytes.length - this.bytes.length;
			for (let i = 0; i < this.bytes.length; i++) {
				newBytes[i + offset] = this.bytes[i];
			}
			this.bytes = newBytes;
		}

		const realIndex = this.bytes.length - 1 - byteIndex;

		if (value) {
			this.bytes[realIndex] |= 1 << bitIndex;
		} else {
			this.bytes[realIndex] &= ~(1 << bitIndex);
		}
	}

	toBase64(): string {
		return btoa(String.fromCharCode(...this.bytes));
	}

	static fromBase64(base64: string): WplaceBitmap {
		return new WplaceBitmap(base64);
	}
}
