#!/bin/bash
# Laser Engraving Converter - Final Vertical Fix

echo "========================================"
echo " LASER ENGRAVING CONVERTER "
echo "========================================"
echo ""

# Get filename
read -p "Enter image name (without .png): " base_name

# Find the file
if [ -f "${base_name}.png" ]; then
  png_file="${base_name}.png"
elif [ -f "${base_name}.PNG" ]; then
  png_file="${base_name}.PNG"
elif [ -f "$base_name" ]; then
  png_file="$base_name"
else
  echo "ERROR: File '${base_name}' not found!"
  read -p "Press Enter to exit..."
  exit 1
fi

echo "Found: $png_file"
gcode_file="${base_name}laser.ngc"
echo "Output: $gcode_file"
echo ""

# Get settings
read -p "Enter target width in mm [20]: " target_width_mm
target_width_mm=${target_width_mm:-20}
read -p "Enter DPI [75]: " dpi_input
dpi=${dpi_input:-75}
read -p "Enter feed rate [500]: " feed_rate_input
feed_rate=${feed_rate_input:-500}
read -p "Enter safe Z height [10]: " safe_z_input
safe_z=${safe_z_input:-10}
read -p "Enter engrave Z height [0]: " engrave_z_input
engrave_z=${engrave_z_input:-0}
read -p "Enter minimum power [1]: " min_power_input
min_power=${min_power_input:-1}
read -p "Enter maximum power [500]: " max_power_input
max_power=${max_power_input:-500}
read -p "Cross-hatching? (y/n) [n]: " cross_hatch_input
cross_hatch=${cross_hatch_input:-n}

echo ""
echo "=== SETTINGS ==="
echo "Image: $png_file"
echo "Width: ${target_width_mm}mm"
echo "DPI: $dpi"
echo "Feed: ${feed_rate} mm/min"
echo "Safe Z: ${safe_z}mm"
echo "Engrave Z: ${engrave_z}mm"
echo "Power: ${min_power}-${max_power}"
echo "Cross-hatch: $cross_hatch"
echo ""

read -p "Continue? (y/n): " confirm
#if ! "$confirm" =~ ^[Yy]$; then  # this doesn't work on Debian Trixie
if [[ "$confirm" == "${confirm#[Yy]}" ]] ;then
  echo "Cancelled."
  read -p "Press Enter to exit..."
  exit 0
fi

echo "Converting..."
echo ""

cat > /tmp/laser_final_fix.py << 'PYTHON_EOF'
''' Tool to convert a grayscale image to G-code for laser engraving
with support for cross-hatching. By raggielyle1(A)gmail.com, 2026-02-09)'''
import sys
import os
from PIL import Image

def main():
  if len(sys.argv) != 11:
    print("ERROR: Wrong number of arguments!")
    return 1
  
  # Parse arguments
  input_file = sys.argv[1]
  target_width_mm = float(sys.argv[2])
  dpi = int(sys.argv[3])
  feed_rate = int(sys.argv[4])
  safe_z = float(sys.argv[5])
  engrave_z = float(sys.argv[6])
  min_power = int(sys.argv[7])
  max_power = int(sys.argv[8])
  cross_hatch = sys.argv[9]
  output_file = sys.argv[10]
  
  print(f"Converting: {os.path.basename(input_file)}")
  print(f"Power range: {min_power}-{max_power}")

  try:
    # Load image
    img = Image.open(input_file)
    if img.mode != 'L':
      img = img.convert('L')
    orig_w, orig_h = img.size
    
    # Calculate new size
    pixels_per_mm = dpi / 25.4
    target_px_w = int(target_width_mm * pixels_per_mm)
    aspect_ratio = orig_h / orig_w
    target_px_h = int(target_px_w * aspect_ratio)
    
    actual_mm_w = target_px_w / pixels_per_mm
    actual_mm_h = target_px_h / pixels_per_mm
    mm_per_pixel = 25.4 / dpi
    
    print(f"Image size: {target_px_w}x{target_px_h} pixels")
    print(f"Physical size: {actual_mm_w:.1f}x{actual_mm_h:.1f} mm")
    print(f"mm per pixel: {mm_per_pixel:.3f}")
  
    # Resize
    img = img.resize((target_px_w, target_px_h))
    pixels = list(img.getdata())
  
    # Generate G-code
    with open(output_file, 'w') as f:
      # Header
      f.write('; Laser engraving - FINAL FIX\n')
      f.write(f'; Image: {os.path.basename(input_file)}\n')
      f.write(f'; Size: {actual_mm_w:.1f}x{actual_mm_h:.1f} mm\n')
      f.write(f'; DPI: {dpi}\n')
      f.write(f'; Feed: {feed_rate}\n')
      f.write(f'; Power: {min_power}-{max_power}\n\n')

      # Setup
      f.write('G21\nG90\nG64\nG17\nG54\n\n')
    
      # Initialize
      f.write(f'F{feed_rate}\n')
      f.write(f'G0 Z{safe_z:.1f}\n')
      f.write('G0 X0 Y0\n')
      f.write(f'G0 Z{engrave_z:.1f}\n')
      f.write('M3\n\n')
    
      # HORIZONTAL PASSES
      f.write('; --- HORIZONTAL PASSES ---\n')
      print("\nGenerating horizontal passes...")
    
      for y in range(target_px_h):
        # Flip Y: image row y (0=top) -> machine Y (target_px_h-1-y)*mm_per_pixel
        y_pos = (target_px_h - 1 - y) * mm_per_pixel
    
        if y % 2 == 0:
          # Left to right
          f.write(f'G0 X0 Y{y_pos:.3f}\n')
          for x in range(target_px_w):
            pixel = pixels[y * target_px_w + x]
            power = min_power + int((max_power - min_power) * (255 - pixel) / 255)
            f.write(f'G1 X{x*mm_per_pixel:.3f} S{power}\n')
        else:
        # Right to left
          f.write(f'G0 X{actual_mm_w:.3f} Y{y_pos:.3f}\n')
          for x in range(target_px_w-1, -1, -1):
            pixel = pixels[y * target_px_w + x]
            power = min_power + int((max_power - min_power) * (255 - pixel) / 255)
            f.write(f'G1 X{x*mm_per_pixel:.3f} S{power}\n')
      
        if y % 50 == 0:
          print(f" Row {y+1}/{target_px_h}")
    
      # VERTICAL PASSES
      if cross_hatch.lower() == 'y':
        f.write('\n; --- VERTICAL PASSES (CROSS-HATCH) ---\n')
      print("\nGenerating vertical passes...")
      print("DEBUG: This should engrave on the way UP, not on the way DOWN!")
    
      for x in range(target_px_w):
        x_pos = x * mm_per_pixel
        if x % 2 == 0:
          # Even columns: bottom to top (engrave on the way UP)
          f.write(f'G0 X{x_pos:.3f} Y0\n')
          # We want to go from Y=0 to Y=max
          # Read pixels from BOTTOM (image row target_px_h-1) to TOP (image row 0)
          for step in range(target_px_h):
            # step: 0 to target_px_h-1 (bottom to top in machine coords)
            # image_y: target_px_h-1 to 0 (bottom to top in image)
            image_y = target_px_h - 1 - step
            pixel = pixels[image_y * target_px_w + x]
            power = min_power + int((max_power - min_power) * (255 - pixel) / 255)
            current_y = step * mm_per_pixel # 0 to max
            f.write(f'G1 Y{current_y:.3f} S{power}\n')
        else:
          # Odd columns: top to bottom (engrave on the way DOWN)
          f.write(f'G0 X{x_pos:.3f} Y{actual_mm_h:.3f}\n')
          # We want to go from Y=max to Y=0
          # Read pixels from TOP (image row 0) to BOTTOM (image row target_px_h-1)
          for step in range(target_px_h):
            # step: 0 to target_px_h-1 (represents position from top)
            image_y = step # 0 to target_px_h-1 (top to bottom in image)
            pixel = pixels[image_y * target_px_w + x]
            power = min_power + int((max_power - min_power) * (255 - pixel) / 255)
            current_y = actual_mm_h - (step * mm_per_pixel) # max to 0
            f.write(f'G1 Y{current_y:.3f} S{power}\n')
        if x % 50 == 0:
          print(f" Column {x+1}/{target_px_w}")
      
      # End program
      f.write('\n; --- END ---\n')
      f.write('M5\n')
      f.write(f'G0 Z{safe_z:.1f}\n')
      f.write('G0 X0 Y0\n')
      f.write('M2\n')
    
    print(f"\n✅ G-code written to: {output_file}")

    # Show sample of vertical section
    if cross_hatch.lower() == 'y' and os.path.exists(output_file):
      with open(output_file, 'r') as f:
        lines = f.readlines()
    
        # Find vertical section
        for i, line in enumerate(lines):
          if 'VERTICAL PASSES' in line:
            print("\n=== SAMPLE OF VERTICAL SECTION ===")
            # Show first 20 lines of vertical section
            for j in range(i, min(i+20, len(lines))):
              print(f" {lines[j].rstrip()}")
            print("...")
          break
    return 0

  except Exception as e:
    print(f"\n❌ ERROR: {e}")
    import traceback
    traceback.print_exc()
    return 1

if __name__ == "__main__":
  sys.exit(main())
PYTHON_EOF

# Run the Python script
python3 /tmp/laser_final_fix.py \
"$png_file" \
"$target_width_mm" \
"$dpi" \
"$feed_rate" \
"$safe_z" \
"$engrave_z" \
"$min_power" \
"$max_power" \
"$cross_hatch" \
"$gcode_file"

result=$?

echo ""
echo "========================================"
if [ $result -eq 0 ]; then
  echo "CONVERSION COMPLETE!"
  echo "File: $gcode_file"
  echo ""
else
  echo "CONVERSION FAILED!"
fi
echo ""

read -p "Press Enter to exit..."
