from steggynography import __project_name__, __version__, bin_to_dec
from steggynography.header import headr_len, parse_headr_bin
from steggynography.errors import ImgFrmtErr, is_valid_img_frmt
import numpy as np
import imageio.v3 as iio

def get_lsb(img : np.ndarray) -> list[int]:
  bin = img.tolist()
  return [b & 0b00000001 for b in bin]

def decode(path_in : str, path_out : str):
  # ensures valid image format
  if not is_valid_img_frmt(path_in):
    raise ImgFrmtErr(path_in)
  
  img = iio.imread(path_in).flatten()
  
  # separates header from payload
  headr_bin = get_lsb(img[:headr_len])
  headr = parse_headr_bin(headr_bin)

  # reads payload
  payld_len = headr[4] * 8
  payld_bin = get_lsb(img[headr_len:headr_len + payld_len])
  
  print(f"Decoding '{path_in}', and writing the results to '{path_out}'...")
  
  payld_txt : list[str] = []
  for i in range(0, payld_len, 8):
    # reads LSB of 8 pixels to form a singular message byte
    payld_byte = [payld_bit for payld_bit in payld_bin[i:i+8]]
    payld_txt += chr(bin_to_dec(payld_byte))

  # writes to file
  with open(path_out, "w") as file:
    file.write("".join(payld_txt))

