import sys
import math
import os

# -----------------------------
# HDGL Encoder/Decoder
# -----------------------------

# Optional Fibonacci delta sequence
FIBS = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233]

# -----------------------------
# Helper Functions
# -----------------------------

def chunk_bytes(data, chunk_size):
    """Yield successive chunks from data."""
    for i in range(0, len(data), chunk_size):
        yield data[i:i + chunk_size]

def bytes_to_vector(b):
    """Convert a bytes chunk to integer vector."""
    return int.from_bytes(b, byteorder='big')

def vector_to_bytes(vector, length=None):
    """Convert integer vector back to bytes."""
    if length is None:
        length = (vector.bit_length() + 7) // 8
    return vector.to_bytes(length, byteorder='big')

def encode_file(input_file, output_file, chunk_size=16):
    """Encode file into HDGL covenant vectors."""
    covenant_lines = []
    fib_index = 0

    with open(input_file, "rb") as f:
        data = f.read()

    for chunk in chunk_bytes(data, chunk_size):
        vector = bytes_to_vector(chunk)
        fib_delta = FIBS[fib_index % len(FIBS)]
        fib_index += 1

        # OP_VEC_DUP and OP_HDGL_VEC_ADD simulated
        covenant_lines.append(f"0x{vector:x} {vector+fib_delta} {vector+fib_delta} OP_WITHINVERIFY")

    with open(output_file, "w") as out:
        for line in covenant_lines:
            out.write(line + "\n")

    print(f"[+] Encoding complete: {output_file}")
    print(f"[+] Total vectors: {len(covenant_lines)}")
    print(f"[+] Original file size: {len(data)} bytes")

def decode_covenant(input_file, output_file):
    """Decode HDGL covenant vectors back into original file."""
    reconstructed_bytes = bytearray()
    fib_index = 0

    with open(input_file, "r") as f:
        for line in f:
            if "OP_WITHINVERIFY" not in line:
                continue
            tokens = line.strip().split()
            vector_hex = tokens[0]
            vector = int(vector_hex, 16)

            fib_delta = FIBS[fib_index % len(FIBS)]
            fib_index += 1

            chunk = vector_to_bytes(vector)
            # Reverse Fibonacci delta
            chunk = bytes((b - fib_delta) % 256 for b in chunk)
            reconstructed_bytes.extend(chunk)

    with open(output_file, "wb") as out:
        out.write(reconstructed_bytes)

    print(f"[+] Decoding complete: {output_file}")
    print(f"[+] Total bytes: {len(reconstructed_bytes)}")

# -----------------------------
# Command-line interface
# -----------------------------

def print_usage():
    print("Usage:")
    print("  Encode: python hdgl_codec.py encode <input_file> <output_covenant_file>")
    print("  Decode: python hdgl_codec.py decode <input_covenant_file> <output_file>")

if __name__ == "__main__":
    if len(sys.argv) != 4:
        print_usage()
        sys.exit(1)

    mode = sys.argv[1]
    input_path = sys.argv[2]
    output_path = sys.argv[3]

    if mode == "encode":
        encode_file(input_path, output_path)
    elif mode == "decode":
        decode_covenant(input_path, output_path)
    else:
        print_usage()
        sys.exit(1)
