from steggynography import __project_name__, __version__, dec_to_bin
from steggynography.header import make_headr_bin
from steggynography.errors import ImgFrmtErr, EncFitErr, is_valid_img_frmt
import imageio.v3 as iio

def payld_to_bin(payld_txt : str) -> list[int]:
  payld_bin : list[int] = []
  for c in payld_txt:
    payld_bin += dec_to_bin(ord(c), 8)

  return payld_bin

def encode(path_in : str, payld_txt : str, path_out : str):
  # ensures valid image format
  if not is_valid_img_frmt(path_in):
    raise ImgFrmtErr(path_in)
  if not is_valid_img_frmt(path_out):
    raise ImgFrmtErr(path_out)

  # reads image (bytes)
  img = iio.imread(path_in)
  img_shape = img.shape
  img = img.flatten()

  # reads and encodes header + payload (bits)
  enc_bin = make_headr_bin(len(payld_txt))
  enc_bin += payld_to_bin(payld_txt)
  if len(enc_bin) > img.size:
    raise EncFitErr(len(enc_bin), img.size)

  print(f"Encoding '{payld_txt}', into '{path_in}' and writing the results to '{path_out}'...")

  for i, enc_bit in enumerate(enc_bin):
    # ensures only last bit is overwritten of image byte
    img[i] = (img[i] & 0b11111110) | enc_bit

  # writes image (pixels) to file
  img = img.reshape(img_shape)
  iio.imwrite(path_out, img)

