# BPC_DocumentArchiveSystem — Document Archive System

**Parent Class:** `ActorComponent`
**Category:** Inventory
**Target UE Version:** 5.5–5.7
**Build Phase:** 3 — Inventory

## 1. Overview

`BPC_DocumentArchiveSystem` manages collected documents — notes, letters, audio logs, data files. Tracks read/unread status, organizes by category, and provides query functions for UI and narrative systems.

## 2. Variables

| Variable | Type | Description |
|----------|------|-------------|
| `CollectedDocuments` | `TArray<S_DocumentEntry>` | All collected documents |
| `DocumentCategories` | `TArray<E_DocumentCategory>` | Notes, Letters, Audio, Data, Photos |
| `bShowUnreadBadge` | `bool` | Highlight unread documents |
| `UnreadCount` | `int32` | Total unread documents |

## 3. Functions

| Function | Description |
|----------|-------------|
| `AddDocument` | Adds a document to the archive |
| `MarkAsRead` | Marks a document as read |
| `MarkAllAsRead` | Marks all as read |
| `GetDocumentsByCategory` | Returns filtered list |
| `GetUnreadCount` | Returns unread count |
| `HasDocument` | Checks if document is collected |

## 4. Event Dispatchers

| Dispatcher | Payload | Description |
|------------|---------|-------------|
| `OnDocumentCollected` | `S_DocumentEntry Document` | New document added |
| `OnDocumentRead` | `FGuid DocumentID` | Document marked read |
| `OnAllDocumentsRead` | — | All documents read |

## 5. Dependencies

| System | Relationship |
|--------|--------------|
| `BPC_InventorySystem` | Documents as inventory items |
| `WBP_JournalDocumentViewer` | UI for viewing documents |
| `BPC_LoreUnlockSystem` | Lore document triggers |

## 6. Reuse Notes
- Documents are inventory items with `E_ItemCategory = Document`

---

## 7. Manual Implementation Guide

### 7.1 Class Setup
1. Create Blueprint Class: Parent = `ActorComponent`, Name = `BPC_DocumentArchiveSystem`
2. Add to Player Character
3. Define struct `S_DocumentEntry` with fields: `DocumentID` (Guid), `DocumentTag` (GameplayTag), `Title` (Text), `Body` (Text), `Category` (Enum), `bIsRead` (Boolean), `DateCollected` (Float), `bIsFlagged` (Boolean)

### 7.2 Variable Initialization (BeginPlay)
```
Event BeginPlay
  ├─ Set CollectedDocuments = empty Array<S_DocumentEntry>
  ├─ Set UnreadCount = 0
  ├─ Set bShowUnreadBadge = true
  ├─ Get Owner → Find Component by Class (BPC_InventorySystem) → Cache
  │    └─ Bind to OnItemAdded → OnItemAddedHandler
  └─ Get Owner → Find BP_DocumentArchiveSystem → self (ensure only one)
```

### 7.3 Function Implementations

#### `AddDocument(ItemData: DA_ItemData)` → `Boolean`

```
[Function: AddDocument]
  Step 1: Branch on ItemData.ItemType == Document → If not, return false
  Step 2: Check if document with same ItemTag already in CollectedDocuments:
    ForEach CollectedDocuments → if Entry.DocumentTag == ItemData.ItemTag:
      Return false (already collected)
  Step 3: Create S_DocumentEntry struct:
    - DocumentID = New Guid
    - DocumentTag = ItemData.ItemTag
    - Title = ItemData.DisplayName
    - Body = ItemData.Description  (document content)
    - Category = determine from tag (ItemTag starts with "Document.Notes" → Notes, etc.)
    - bIsRead = false
    - DateCollected = Get Game Time in Seconds
    - bIsFlagged = false
  Step 4: Add to CollectedDocuments array
  Step 5: UnreadCount += 1
  Step 6: Fire OnDocumentCollected(NewEntry)
  Step 7: Also notify BPC_LoreUnlockSystem if category is Lore
  Step 8: Return true
```

**Nodes:** `New Guid`, `Make S_DocumentEntry`, `Add`, `Get Game Time in Seconds`, `Starts With (String)`

#### `MarkAsRead(DocumentID: Guid)` → `void`

```
[Function: MarkAsRead]
  Step 1: Find document in CollectedDocuments by DocumentID:
    ForEach with Break → if Entry.DocumentID == DocumentID:
      Branch on Entry.bIsRead:
        False → Set bIsRead = true, UnreadCount -= 1
        True → Return (already read)
  Step 2: Fire OnDocumentRead(DocumentID)
  Step 3: Branch on UnreadCount == 0:
    True → Fire OnAllDocumentsRead
```

#### `MarkAllAsRead()` → `void`

```
[Function: MarkAllAsRead]
  Step 1: ForEach CollectedDocuments:
    Set bIsRead = true
  Step 2: Set UnreadCount = 0
  Step 3: Fire OnAllDocumentsRead
```

#### `GetDocumentsByCategory(Category: E_DocumentCategory, bUnreadOnly: Boolean)` → `Array<S_DocumentEntry>`

```
[Function: GetDocumentsByCategory] (Pure)
  Step 1: Create empty Array → Results
  Step 2: ForEach CollectedDocuments:
    If Entry.Category == Category AND (NOT bUnreadOnly OR NOT Entry.bIsRead):
      Add to Results
  Step 3: Return Results
```

#### `GetUnreadCount()` → `Integer`

```
[Function: GetUnreadCount] (Pure)
  Return UnreadCount
```

#### `HasDocument(DocumentTag: GameplayTag)` → `Boolean`

```
[Function: HasDocument] (Pure)
  Step 1: ForEach CollectedDocuments:
    If Entry.DocumentTag == DocumentTag → Return true
  Step 2: Return false
```

#### `ToggleFlag(DocumentID: Guid)` → `void`

```
[Function: ToggleFlag]
  Step 1: Find document by DocumentID in CollectedDocuments
  Step 2: Entry.bIsFlagged = NOT Entry.bIsFlagged
  Step 3: If flagged → move to top of array (optional sorting)
```

### 7.4 Event Dispatcher Bindings
| Bind to Dispatcher | Custom Event | Logic |
|-------------------|-------------|-------|
| `BPC_InventorySystem.OnItemAdded(Item)` | `OnItemAddedHandler` | If Item.ItemData.ItemType == Document → Call AddDocument(Item.ItemData) |

### 7.5 Blueprint Build Checklist
- [ ] Define enum `E_DocumentCategory`: Notes, Letters, Audio, Data, Photos
- [ ] Define struct `S_DocumentEntry` with all fields
- [ ] Create BPC_DocumentArchiveSystem, add to Player Character
- [ ] Add variables: CollectedDocuments, DocumentCategories, bShowUnreadBadge, UnreadCount
- [ ] Implement AddDocument with duplicate check and struct creation
- [ ] Implement MarkAsRead with UnreadCount tracking
- [ ] Implement GetDocumentsByCategory with optional unread filter
- [ ] Implement HasDocument for narrative queries
- [ ] Bind to BPC_InventorySystem.OnItemAdded
- [ ] Test: pick up document item → archive updates → UI shows badge