#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import wave
import struct
import zlib
import numpy as np

SR = 44100
SKIP_SEC = 1.0
STEP = 2
IN_WAV = "some_secret.wav"

def read_wav_int16(path: str):
    with wave.open(path, "rb") as wf:
        assert wf.getnchannels() == 2
        assert wf.getsampwidth() == 2
        sr = wf.getframerate()
        frames = wf.readframes(wf.getnframes())
    arr = np.frombuffer(frames, dtype=np.int16).reshape(-1, 2)
    return sr, arr

def bits_to_bytes_big_endian(bits: np.ndarray) -> bytes:
    # Длина должна быть кратна 8
    n = (bits.size + 7) // 8 * 8
    if n != bits.size:
        bits = np.pad(bits, (0, n - bits.size), constant_values=0)
    by = np.packbits(bits.astype(np.uint8), bitorder='big').tobytes()
    return by

def extract_header_and_length(right: np.ndarray, sr: int):
    skip = int(sr * SKIP_SEC)
    # Считываем первые 12 байт (заголовок: 4 + 4 + 4)
    header_bits_count = 12 * 8
    idxs = skip + np.arange(header_bits_count) * STEP
    bits = (right[idxs] & 1).astype(np.uint8)
    header = bits_to_bytes_big_endian(bits)
    magic = header[:4]
    if magic != b"STAG":
        raise ValueError("Магия заголовка не совпала — это не тот контейнер.")
    length = struct.unpack(">I", header[4:8])[0]
    crc = struct.unpack(">I", header[8:12])[0]
    return length, crc

def extract_all(sr: int, stereo: np.ndarray):
    right = stereo[:, 1]
    length, crc_expected = extract_header_and_length(right, sr)
    total_bytes = 12 + length
    total_bits = total_bytes * 8
    skip = int(sr * SKIP_SEC)
    idxs = skip + np.arange(total_bits) * STEP
    bits = (right[idxs] & 1).astype(np.uint8)
    data = bits_to_bytes_big_endian(bits)
    header = data[:12]
    payload = data[12:12+length]
    crc_actual = zlib.crc32(payload) & 0xFFFFFFFF
    if crc_actual != crc_expected:
        raise ValueError("CRC не сошлась — данные повреждены или неверные параметры извлечения.")
    flag = zlib.decompress(payload).decode("utf-8")
    return flag

def main():
    sr, stereo = read_wav_int16(IN_WAV)
    flag = extract_all(sr, stereo)
    print("[+] DATA [ ", flag, " ]")

if __name__ == "__main__":
    main()
