# To AI Agent: Fix EXIF GPS Extraction, Implement Client-Side 2K Image Resizing, and Fix Android Fullscreen Lightbox Alignment

## 1. Context & Feature Objectives
We are addressing three crucial image-handling and layout bugs on the mobile/Android web wrapper:
1. **Fix (Missing EXIF Location):** When users upload photos, the system fails to extract the geographic coordinates (Latitude/Longitude) embedded within the image metadata. We need to parse EXIF data completely on the client side before submission.
2. **Feat (Native Save & 2K Downscale):** Whether the user shoots a new photo via the Camera or picks one from the Gallery, the original image must remain safely stored in the phone's native album (handled by native webview permissions). Before uploading the file to our Debian server, the frontend must dynamically resize/downscale the image to a maximum resolution of **2K (2048px on its longest edge)** to optimize network bandwidth and server storage.
3. **Bug (Fullscreen Viewer Displacement):** When clicking an image inside the gallery/photo manager view to preview it in fullscreen mode on an Android device, the image incorrectly aligns to the absolute bottom edge of the viewport instead of centering beautifully.

---

## 2. Technical Execution Strategy

### 2.1. Client-Side EXIF Processing & Metadata Preservation
Standard browser file inputs often strip EXIF headers during dynamic manipulation or fail to parse them natively. We will introduce `exif-js` or use a standard binary array buffer scanner to extract the `GPSLatitude` and `GPSLongitude` headers right before resizing occurs, attaching them to the final multipart upload payload.

### 2.2. Downscaling to 2K via HTML5 Canvas
To achieve hardware-accelerated image scaling on mobile devices without losing core image visibility, the source image will be rendered onto an offscreen `<canvas>` container configured to enforce a `max-dimension` of `2048px`, maintaining the original aspect ratio.

### 2.3. Flexbox/Absolute Centering Fix for Android Lightbox
The bottom-displacement bug is tied to incorrect layout bounds calculations on mobile screens when toolbars or navigation rows shift view heights. We will refactor the Lightbox container modal to use rigid viewport configurations (`fixed inset-0`) along with standard vertical centering mechanics.

---

## 3. Code Refactoring Blueprint

### Step 1: Implement Image Metadata Picker & 2K Resizer Logic (`imageProcessor.ts`)
Create a utility service at `frontend/src/utils/imageProcessor.ts` to handle metadata extraction and canvas downscaling sequentially:

```typescript
import EXIF from 'exif-js';

interface ProcessedImageResult {
  file: Blob;
  latitude: number | null;
  longitude: number | null;
}

// Helper to convert EXIF rational coordinates to standard decimal degrees
const convertDMSToDD = (dms: number[], ref: string): number => {
  if (!dms || dms.length < 3) return 0;
  const degrees = dms[0] + dms[1] / 60 + dms[2] / 3600;
  return ref === 'S' || ref === 'W' ? -degrees : degrees;
};

export const processAndResizeImage = (file: File): Promise<ProcessedImageResult> => {
  return new Promise((resolve) => {
    let latitude: number | null = null;
    let longitude: number | null = null;

    // 1. EXTRACT EXIF METADATA BEFORE CANVAS CLEARING
    EXIF.getData(file as any, function (this: any) {
      const allTags = EXIF.getAllTags(this);
      if (allTags.GPSLatitude && allTags.GPSLatitudeRef) {
        latitude = convertDMSToDD(allTags.GPSLatitude, allTags.GPSLatitudeRef);
      }
      if (allTags.GPSLongitude && allTags.GPSLongitudeRef) {
        longitude = convertDMSToDD(allTags.GPSLongitude, allTags.GPSLongitudeRef);
      }
      
      console.log(`📸 Extracted EXIF Metadata - Lat: ${latitude}, Lng: ${longitude}`);
      
      // Proceed directly to resizing stage
      proceedToResize();
    });

    function proceedToResize() {
      const reader = new FileReader();
      reader.readAsDataURL(file);
      reader.onload = (event) => {
        const img = new Image();
        img.src = event.target?.result as string;
        img.onload = () => {
          const canvas = document.createElement('canvas');
          let width = img.width;
          let height = img.height;
          const MAX_SIZE = 2048; // Enforce rigid 2K maximum boundary limit

          // Calculate ideal bounding proportions
          if (width > height) {
            if (width > MAX_SIZE) {
              height = Math.round((height * MAX_SIZE) / width);
              width = MAX_SIZE;
            }
          } else {
            if (height > MAX_SIZE) {
              width = Math.round((width * MAX_SIZE) / height);
              height = MAX_SIZE;
            }
          }

          canvas.width = width;
          canvas.height = height;
          const ctx = canvas.getContext('2d');
          if (!ctx) return resolve({ file, latitude, longitude });

          // Render image onto downscaled dimensions canvas bounding box
          ctx.drawImage(img, 0, 0, width, height);
          
          canvas.toBlob((blob) => {
            if (blob) {
              resolve({
                file: blob,
                latitude,
                longitude
              });
            } else {
              resolve({ file, latitude, longitude });
            }
          }, 'image/jpeg', 0.88); // 88% quality compression sweet-spot
        };
      };
    }
  });
};

### Step 2: Update Image Upload Handler Layer
Integrate the processor wrapper inside your central upload function (e.g., ImageUploader.tsx or your form submission handler):

import { processAndResizeImage } from '../../utils/imageProcessor';

const handleFileUpload = async (event: React.ChangeEvent<HTMLInputElement>) => {
  const targetFile = event.target.files?.[0];
  if (!targetFile) return;

  try {
    // 1. Process image: Reads EXIF data and forces 2K resizing on device memory
    const { file, latitude, longitude } = await processAndResizeImage(targetFile);

    const formData = new FormData();
    formData.append('image', file, 'yotrip_upload.jpg');
    
    // 2. Append coordinates safely to standard server fields
    if (latitude !== null && longitude !== null) {
      formData.append('latitude', latitude.toString());
      formData.append('longitude', longitude.toString());
    }

    // 3. Post to API endpoint
    const response = await api.post('/media/upload', formData, {
      headers: { 'Content-Type': 'multipart/form-data' }
    });
    
    console.log("✅ Media successfully synchronized with server backend:", response.data);
  } catch (error) {
    console.error("Failed to safely prepare media stream:", error);
  }
};

### Step 3: Fix Fullscreen Image Alignment Layout (ImageLightbox.tsx)
Locate your photo viewer overlay or modal drawer component. Overhaul the tailwind utilities to guarantee true vertical and horizontal centering layout balance on Android devices:

{/* ❌ BEFORE: Faulty container pinning images to device bottom edges */}
<div className="fixed inset-0 bg-black flex items-end justify-center">

{/* ✅ AFTER: True viewport overlay centering bounding context */}
<div className="fixed inset-0 bg-black/95 backdrop-blur-sm flex flex-col items-center justify-center z-[999999] overflow-hidden animate-fade-in">
  {/* Close Button Top Tracker Bar Container */}
  <div className="absolute top-4 right-4 z-50">
    <button className="p-2.5 bg-slate-900/60 rounded-full text-white">✕</button>
  </div>

  {/* Image wrapper frame context forcing clean alignment metrics */}
  <div className="w-full h-full flex items-center justify-center p-4">
    <img 
      src={currentImageUrl} 
      alt="YoTrip Preview" 
      className="max-w-full max-h-full object-contain select-none pointer-events-auto"
      style={{
        /* Prevent Android webviews from accidental shifting behaviors */
        transform: 'translate3d(0, 0, 0)'
      }}
    />
  </div>
</div>

## 4. Automated Verification Checklist for AI Agent
[ ] EXIF Validation Verification: Test uploading a photo embedded with active geolocation values. Inspect the API outgoing transmission payload in the network panel; latitude and longitude fields must contain accurate decimal metrics instead of blank string indicators.

[ ] Longest-Edge Constraint Check: Upload a ultra-high resolution image (e.g., 4000px wide). Verify that the processed file size shrinks significantly, and confirm through terminal logging that the generated canvas asset limits width/height strictly to 2048px.

[ ] Android Centering Success: Activate the image preview mode inside the Android Simulator. The image layout must align mathematically dead-center vertically, leaving symmetric padding bars on both the top header and bottom system navigation boundaries.