#!/usr/bin/env python
# Copyright (c) 2023 Dominic Masters
# 
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT

from PIL import Image
import argparse
import os

# Args
parser = argparse.ArgumentParser(description='Converts image textures to internal game data format.')
parser.add_argument('-i', '--input');
parser.add_argument('-o', '--output');
parser.add_argument('-s', '--scale');
parser.add_argument('-sf', '--scale-filter');
parser.add_argument('-wx', '--wrap-x');
parser.add_argument('-wy', '--wrap-y');
parser.add_argument('-fi', '--filter-min')
parser.add_argument('-fg', '--filter-mag')
parser.add_argument('-csx', '--crop-start-x');
parser.add_argument('-csy', '--crop-start-y');
parser.add_argument('-cex', '--crop-end-x');
parser.add_argument('-cey', '--crop-end-y');
args = parser.parse_args()

# Ensure input exists
if not os.path.exists(args.input):
  print(f"Input file '{args.input}' does not exist.")
  exit(1)

# Open image
img = Image.open(args.input)

# Normalize the image
hasAlpha = img.mode == 'RGBA' or img.mode == 'LA'

# Convert the image to RGB or RGBA mode based on alpha channel
if hasAlpha:
  img = img.convert('RGBA')
else:
  img = img.convert('RGB')

  # Apply cropping
crop_box = [
  int(args.crop_start_x) if args.crop_start_x not in (None, "") else 0,
  int(args.crop_start_y) if args.crop_start_y not in (None, "") else 0,
  int(args.crop_end_x) if args.crop_end_x not in (None, "") else img.width,
  int(args.crop_end_y) if args.crop_end_y not in (None, "") else img.height
]
img = img.crop(crop_box)
  
# Apply scaling
if args.scale not in (None, ""):
  scale = float(args.scale)
  newSize = (int(img.width * scale), int(img.height * scale))
  if args.scale_filter == 'NEAREST':
    img = img.resize(newSize, Image.NEAREST)
  elif args.scale_filter == 'BILINEAR':
    img = img.resize(newSize, Image.BILINEAR)
  elif args.scale_filter == 'BICUBIC':
    img = img.resize(newSize, Image.BICUBIC)
  elif args.scale_filter == 'LANCZOS':
    img = img.resize(newSize, Image.LANCZOS)
  else:
    img = img.resize(newSize)


# Filter
if args.filter_min.lower() == 'NEAREST':
  filterMin = 0
else:
  filterMin = 1

if args.filter_mag.lower() == 'NEAREST':
  filterMag = 0
else:
  filterMag = 1

# Wrap
if args.wrap_x.lower() == 'repeat':
  wrapX = 0
elif args.wrap_x.lower() == 'mirror':
  wrapX = 1
elif args.wrap_x.lower() == 'clamp':
  wrapX = 2
elif args.wrap_x.lower() == 'border':
  wrapX = 3
else:
  wrapX = 2

if args.wrap_y.lower() == 'repeat':
  wrapY = 0
elif args.wrap_y.lower() == 'mirror':
  wrapY = 1
elif args.wrap_y.lower() == 'clamp':
  wrapY = 2
elif args.wrap_y.lower() == 'border':
  wrapY = 3
else:
  wrapY = 2

# Get raw pixel data
buffer = img.tobytes()

# Create the output directory if it doesn't exist
os.makedirs(os.path.dirname(args.output), exist_ok=True)

# Write the image metadata and pixel data to the output file
with open(args.output, 'wb') as f:
  header = f"DT_2.00|{img.width}|{img.height}|{4 if hasAlpha else 3}|{wrapX}|{wrapY}|{filterMin}|{filterMag}|"
  f.write(header.encode())
  f.write(buffer)