# Media Tagging System

A comprehensive photo and video tagging system for the Gooner Training Academy web application.

## Features

- **Individual Tagging**: Add multiple tags to single photos or videos
- **Bulk Tagging**: Select multiple media items and apply tags to all at once
- **Tag Management**: Create, rename, delete, and organize tags with custom colors
- **Tag Filtering**: Filter media library by tags (AND/OR logic)
- **Autocomplete**: Tag suggestions while typing based on existing tags
- **Campaign Integration**: Tagging tasks can be integrated into campaign levels
- **Statistics**: Track tag usage, most popular tags, and tagging progress

## Components

### Core Classes

#### MediaTagManager
The backend manager for all tagging operations.

```javascript
// Initialize (automatically done in library.html)
const tagManager = new MediaTagManager(window.game.dataManager);

// Create tags
const tag = tagManager.createTag('selfie', '#FF6B6B');

// Add tags to media
tagManager.addTagsToMedia('photo_123.jpg', ['selfie', 'outfit']);

// Bulk operations
tagManager.bulkAddTags(['photo_1.jpg', 'photo_2.jpg'], ['bedroom', 'lingerie']);

// Query tags
const photos = tagManager.getMediaWithTag('selfie');
const tags = tagManager.getTagsForMedia('photo_123.jpg');

// Search tags
const results = tagManager.searchTags('self');
```

#### MediaTagUI
The UI component for rendering tagging interfaces.

```javascript
// Initialize (automatically done in library.html)
const tagUI = new MediaTagUI(tagManager);

// Render tag input
tagUI.renderTagInput(containerElement, 'photo_123.jpg');

// Render tag chips for a media item
tagUI.renderMediaTags(containerElement, 'photo_123.jpg', editable=true);

// Render tag filter panel
tagUI.renderTagFilter(containerElement);

// Open tag management modal
tagUI.openTagManagementModal();

// Enable bulk selection mode
tagUI.enableBulkMode();
tagUI.toggleMediaSelection('photo_123.jpg');
```

#### CampaignTagging
Integration for campaign levels requiring tagging.

```javascript
// Initialize
const campaignTagging = new CampaignTagging(tagManager, tagUI);

// Setup tagging task
campaignTagging.initializeTaggingTask({
    requiredTags: ['outfit', 'pose'],  // Must use these tags
    requiredTagCount: 2,                // At least 2 tags per item
    targetMediaIds: ['photo_1.jpg', 'photo_2.jpg'],  // Specific items
    onComplete: (progress) => {
        console.log('Tagging task completed!', progress);
        // Advance to next level, award points, etc.
    }
});

// Display the interface
const mediaItems = [
    { id: 'photo_1.jpg', url: 'path/to/photo1.jpg', type: 'photo' },
    { id: 'photo_2.jpg', url: 'path/to/photo2.jpg', type: 'photo' }
];
campaignTagging.displayTaggingInterface(containerElement, mediaItems);
```

## Usage in Library

### Accessing the Tagging System

The library.html page automatically initializes the tagging system. Access it via:

```javascript
// Available globally after page load
mediaTagManager  // The tag manager instance
mediaTagUI       // The UI component instance
```

### Managing Tags

1. **Open Tag Management**: Click the "🏷️ Manage Tags" button in the library header
2. **Create Tags**: Enter tag name and optionally choose a color
3. **Edit Tags**: Rename tags or change their colors
4. **Delete Tags**: Remove unused tags (removes from all media)
5. **View Statistics**: See tag usage and most popular tags

### Tagging Photos/Videos

#### Single Item Tagging

1. Navigate to the Gallery or Video tab
2. Click the "+ Tag" button on any item
3. Enter tags (comma-separated) in the input field
4. Press Enter or click "Add"

#### Bulk Tagging

1. Click "📋 Select Multiple" to enter bulk mode
2. Click on media items to select them
3. Click "🏷️ Tag Selected" in the bottom bar
4. Enter tags and press Enter or click "Add"
5. All selected items will be tagged

### Filtering by Tags

1. Open the tag filter panel (automatically shown in Gallery and Video tabs)
2. Check the tags you want to filter by
3. Choose filter mode:
   - **Any**: Show media with ANY of the selected tags (OR logic)
   - **All**: Show media with ALL selected tags (AND logic)
4. Click "Clear Filters" to show all media again

## Usage in Campaign Levels

### Basic Example

```javascript
// In a campaign level's task configuration
{
    id: 'photo-tagging-intro',
    title: 'Photo Organization 101',
    description: 'Tag your photos to organize your collection',
    type: 'tagging-task',
    
    setup: async function() {
        // Get photos that need tagging
        const photos = await window.desktopFileManager.loadCapturedPhotos();
        const recentPhotos = photos.slice(0, 5);  // Last 5 photos
        
        // Initialize tagging system
        const tagManager = new MediaTagManager(window.game.dataManager);
        const tagUI = new MediaTagUI(tagManager);
        const campaignTagging = new CampaignTagging(tagManager, tagUI);
        
        // Setup task
        campaignTagging.initializeTaggingTask({
            requiredTagCount: 1,  // At least 1 tag per photo
            targetMediaIds: recentPhotos.map(p => p.path),
            onComplete: (progress) => {
                window.game.completeTask();
                window.game.showNotification('Great job organizing your photos!', 'success');
            }
        });
        
        // Display interface
        const container = document.getElementById('task-container');
        const mediaItems = recentPhotos.map(photo => ({
            id: photo.path,
            url: photo.url,
            type: 'photo'
        }));
        
        campaignTagging.displayTaggingInterface(container, mediaItems);
    }
}
```

### Advanced Example with Required Tags

```javascript
{
    id: 'outfit-categorization',
    title: 'Outfit Categorization',
    description: 'Categorize your outfit photos with specific tags',
    
    setup: async function() {
        const photos = await window.desktopFileManager.loadCapturedPhotos();
        const outfitPhotos = photos.filter(p => p.sessionType === 'dress-up');
        
        const tagManager = new MediaTagManager(window.game.dataManager);
        const tagUI = new MediaTagUI(tagManager);
        const campaignTagging = new CampaignTagging(tagManager, tagUI);
        
        campaignTagging.initializeTaggingTask({
            requiredTags: ['clothing-type', 'color', 'style'],  // Must include these
            requiredTagCount: 3,  // Plus any others
            targetMediaIds: outfitPhotos.slice(0, 10).map(p => p.path),
            onComplete: (progress) => {
                // Award points based on tag variety
                const allTags = new Set();
                Object.values(progress.details).forEach(detail => {
                    detail.tags.forEach(tag => allTags.add(tag));
                });
                
                const points = allTags.size * 10;
                window.game.awardPoints(points);
                window.game.completeTask();
            }
        });
        
        const container = document.getElementById('task-container');
        const mediaItems = outfitPhotos.slice(0, 10).map(photo => ({
            id: photo.path,
            url: photo.url,
            type: 'photo'
        }));
        
        campaignTagging.displayTaggingInterface(container, mediaItems);
    }
}
```

## Data Structure

### Tag Object
```javascript
{
    id: "tag_1234567890_abc123",
    name: "selfie",
    color: "#FF6B6B",
    createdAt: 1234567890000,
    usageCount: 15
}
```

### Media Tags Storage
```javascript
{
    version: "1.0",
    tags: [...],  // Array of tag objects
    mediaTags: {
        "photo_123.jpg": ["tag_id_1", "tag_id_2"],
        "video_456.mp4": ["tag_id_3"]
    },
    lastUpdated: 1234567890000
}
```

## API Reference

### MediaTagManager Methods

- `createTag(name, color)` - Create a new tag
- `deleteTag(tagId)` - Delete a tag
- `renameTag(tagId, newName)` - Rename a tag
- `updateTagColor(tagId, color)` - Change tag color
- `addTagsToMedia(mediaId, tagNames)` - Add tags to media
- `removeTagFromMedia(mediaId, tagId)` - Remove tag from media
- `bulkAddTags(mediaIds, tagNames)` - Bulk add tags
- `bulkRemoveTag(mediaIds, tagId)` - Bulk remove tag
- `getTagsForMedia(mediaId)` - Get all tags for media
- `getMediaWithTag(tagId)` - Find media with specific tag
- `getMediaWithAllTags(tagIds)` - AND search
- `getMediaWithAnyTags(tagIds)` - OR search
- `searchTags(query)` - Search tags by name
- `getAllTags()` - Get all tags
- `getStatistics()` - Get tagging statistics
- `exportTags()` - Export tag data
- `importTags(data, merge)` - Import tag data

### MediaTagUI Methods

- `renderTagInput(container, mediaId)` - Render tag input field
- `renderMediaTags(container, mediaId, editable)` - Render tag chips
- `renderTagManagementModal()` - Show tag management modal
- `renderTagFilter(container)` - Render filter panel
- `openTagManagementModal()` - Open tag management
- `enableBulkMode()` - Enable bulk selection
- `disableBulkMode()` - Disable bulk selection
- `toggleMediaSelection(mediaId)` - Toggle item selection
- `selectAllMedia(mediaIds)` - Select all items
- `clearSelection()` - Clear selection
- `getFilteredMedia(allMedia)` - Apply filters to media list

### CampaignTagging Methods

- `initializeTaggingTask(config)` - Setup tagging task
- `checkProgress()` - Check completion status
- `displayTaggingInterface(container, mediaItems)` - Show UI
- `validateAndComplete(wrapper)` - Validate and complete task

## Events

### tagsChanged Event
Fired when tags are added, removed, or modified.

```javascript
window.addEventListener('tagsChanged', (event) => {
    console.log('Tags updated:', event.detail);
    // event.detail.tags - all tags
    // event.detail.statistics - tag statistics
});
```

### tagFiltersChanged Event
Fired when tag filters are changed.

```javascript
window.addEventListener('tagFiltersChanged', (event) => {
    console.log('Filters changed:', event.detail);
    // event.detail.activeFilters - selected tag IDs
    // event.detail.filterMode - 'any' or 'all'
});
```

## Styling

The tagging system uses CSS variables for theming. Key styles are in:
- `src/styles/media-tags.css` - Main tagging styles
- Uses color variables from `src/styles/color-variables.css`

### Custom Styling Example

```css
/* Override tag chip colors */
.tag-chip {
    border-radius: 20px;
    font-weight: bold;
}

/* Custom tag filter panel */
.tag-filter-panel {
    background: linear-gradient(135deg, var(--bg-secondary), var(--bg-primary));
}
```

## Best Practices

1. **Tag Naming**: Use lowercase, descriptive tags (e.g., 'selfie', 'bedroom', 'lingerie')
2. **Tag Categories**: Organize tags into categories (outfit, location, pose, etc.)
3. **Bulk Operations**: Use bulk tagging for similar content to save time
4. **Filtering**: Combine multiple tags with AND/OR logic for precise filtering
5. **Campaign Integration**: Use tagging tasks to encourage organization and engagement
6. **Color Coding**: Use consistent colors for tag categories

## Troubleshooting

### Tags not saving
- Ensure `window.game.dataManager` is available
- Check browser console for errors
- Verify localStorage is not full

### Bulk selection not working
- Make sure bulk mode is enabled (button shows "✓ Select Mode Active")
- Gallery must be in the correct tab (Gallery or Video)

### Campaign task not completing
- Check that all required tags are used
- Verify minimum tag count is met for each item
- Use "Check Progress" button to see detailed status

## Future Enhancements

Potential features for future versions:
- Tag hierarchy (parent/child relationships)
- Tag aliases (multiple names for same concept)
- Automatic tagging suggestions based on AI
- Tag-based collections/albums
- Export/import tag configurations
- Tag-based slideshows
- Advanced search with tag operators
