# URL State Management Implementation

## Overview
This feature allows users to:
1. **Bookmark** their progress through the navigation flow
2. **Refresh** the page without losing their selections
3. **Share** URLs with specific products or navigation states
4. **Deep link** directly to products

## URL Parameter Structure

### Query Parameters
- `b` - Bitwise value representing all selections (integer)
- `q` - Current question ID (string)
- `p` - Product code for direct product view (string)

### Examples
```
# At start
https://yoursite.com/

# After selecting Door > Storm Door > Aluminum
https://yoursite.com/?b=16401&q=q-dimensions

# Viewing a specific product
https://yoursite.com/?p=BGIST&b=16401

# Bit value 16401 decodes to:
# - Door (bit 0)
# - Aluminum (bit 4)
# - Storm Door subtype (bit 14)
```

## Implementation Code

### 1. Add to Global Variables (top of script.js)
```javascript
// Add these to existing global variables
let accumulatedBitValue = 0;
let bitwiseData = {};

// Bit definitions (must match generate_bitwise_helper.py)
const BIT_DEFINITIONS = {
    // Base Types
    'base_door': 0,          // 1
    'base_window': 1,        // 2
    
    // Flags
    'is_accessory': 2,       // 4
    'specific_item': 3,      // 8
    
    // Materials
    'material_aluminum': 4,   // 16
    'material_vinyl': 5,      // 32
    
    // Colors
    'color_black': 6,         // 64
    'color_white': 7,         // 128
    'color_bronze': 8,        // 256
    'color_tan': 9,           // 512
    'color_mill': 10,         // 1024
    'color_sandstone': 11,    // 2048
    
    // Subtypes (from bitwise_legend.json)
    'subtype_patio_door': 12,      // 4096
    'subtype_primary_window': 13,  // 8192
    'subtype_storm_door': 14,      // 16384
    'subtype_storm_window': 15     // 32768
};
```

### 2. Update init() Function
```javascript
function init() {
    // Load all data files (including bitwise)
    Promise.all([
        fetch('data/navigation.json').then(r => r.json()),
        fetch('data/products.json').then(r => r.json()),
        fetch('data/accessories.json').then(r => r.json()),
        fetch('data/product_bitwise.json').then(r => r.json())
    ])
    .then(([questions, products, accessories, bitwise]) => {
        questionData = questions;
        productData = products;
        accessoryData = accessories;
        
        // Index bitwise data by product code
        bitwiseData = {};
        bitwise.forEach(item => {
            bitwiseData[item.PROD_CODE] = item.BIT_VALUE;
        });
        
        // Initialize from URL or start fresh
        initFromURL();
    })
    .catch(error => {
        console.error('Error loading data:', error);
        showError('Failed to load application data.');
    });
}
```

### 3. URL Initialization
```javascript
function initFromURL() {
    const params = new URLSearchParams(window.location.search);
    
    // Priority 1: Direct product view
    const productCode = params.get('p');
    if (productCode) {
        accumulatedBitValue = parseInt(params.get('b') || '0', 10);
        showProductByCode(productCode);
        return;
    }
    
    // Priority 2: Restore navigation state
    const bitValue = params.get('b');
    const questionKey = params.get('q');
    
    if (bitValue && questionKey) {
        accumulatedBitValue = parseInt(bitValue, 10);
        restoreStateFromBitValue(accumulatedBitValue, questionKey);
        return;
    }
    
    // Priority 3: Start fresh
    loadContent('start');
}

function restoreStateFromBitValue(bitValue, questionKey) {
    // Decode bit value back to user selections
    
    // Base type
    if (bitValue & 1) {
        userAnswers['start'] = 'Door';
    } else if (bitValue & 2) {
        userAnswers['start'] = 'Window';
    }
    
    // Materials
    if (bitValue & 16) {
        userAnswers['q-material.material'] = 'Aluminum';
    } else if (bitValue & 32) {
        userAnswers['q-material.material'] = 'Vinyl';
    }
    
    // Colors
    const colorMap = {
        64: 'Black',
        128: 'White',
        256: 'Bronze',
        512: 'Tan',
        1024: 'Mill',
        2048: 'Sandstone'
    };
    
    for (const [bit, color] of Object.entries(colorMap)) {
        if (bitValue & parseInt(bit)) {
            userAnswers['q-color.color'] = color;
            break; // Only store first color found
        }
    }
    
    // Subtypes
    const subtypeMap = {
        4096: 'Patio Door',
        8192: 'Primary Window',
        16384: 'Storm Door',
        32768: 'Storm Window'
    };
    
    for (const [bit, subtype] of Object.entries(subtypeMap)) {
        if (bitValue & parseInt(bit)) {
            userAnswers['q-subtype'] = subtype;
            break; // Only store first subtype found
        }
    }
    
    // Navigate to the saved question
    history = ['start'];
    if (questionKey !== 'start') {
        history.push(questionKey);
    }
    loadContent(questionKey);
}
```

### 4. Update URL on Each Selection
```javascript
function updateURL(questionKey = null) {
    const params = new URLSearchParams();
    
    if (accumulatedBitValue > 0) {
        params.set('b', accumulatedBitValue.toString());
    }
    
    if (questionKey) {
        params.set('q', questionKey);
    } else if (history.length > 0) {
        params.set('q', history[history.length - 1]);
    }
    
    const newURL = window.location.pathname + (params.toString() ? '?' + params.toString() : '');
    window.history.replaceState(
        { 
            bitValue: accumulatedBitValue,
            questionKey: questionKey 
        }, 
        '', 
        newURL
    );
}

function updateBitValue(answerObject) {
    if (!answerObject.filter) return;
    
    const filter = answerObject.filter;
    
    // Base type
    if (filter.baseType === 'Door') {
        accumulatedBitValue |= (1 << BIT_DEFINITIONS['base_door']);
    } else if (filter.baseType === 'Window') {
        accumulatedBitValue |= (1 << BIT_DEFINITIONS['base_window']);
    }
    
    // Materials
    if (filter.material === 'Aluminum') {
        accumulatedBitValue |= (1 << BIT_DEFINITIONS['material_aluminum']);
    } else if (filter.material === 'Vinyl') {
        accumulatedBitValue |= (1 << BIT_DEFINITIONS['material_vinyl']);
    }
    
    // Colors
    const colorKey = filter.color ? 'color_' + filter.color.toLowerCase() : null;
    if (colorKey && BIT_DEFINITIONS[colorKey]) {
        accumulatedBitValue |= (1 << BIT_DEFINITIONS[colorKey]);
    }
    
    // Subtypes
    const subtypeKey = filter.subType ? 'subtype_' + filter.subType.toLowerCase().replace(/ /g, '_') : null;
    if (subtypeKey && BIT_DEFINITIONS[subtypeKey]) {
        accumulatedBitValue |= (1 << BIT_DEFINITIONS[subtypeKey]);
    }
}
```

### 5. Update handleAnswer Function
```javascript
function handleAnswer(currentKey, answerValue, answerIndex) {
    const currentQuestion = questionData[currentKey];
    const answerObject = currentQuestion.answers[answerIndex];
    
    // Store the answer
    userAnswers[currentKey] = answerValue;
    
    // Update bit value based on selection
    updateBitValue(answerObject);
    
    // Resolve the next question (handles conditionals)
    const nextKey = resolveNextQuestion(currentKey, answerValue, answerObject);
    
    history.push(nextKey);
    
    // Update URL with new state
    updateURL(nextKey);
    
    loadContent(nextKey);
}
```

### 6. Product View with URL
```javascript
function showProductByCode(productCode) {
    const product = productData.find(p => p.productCode === productCode);
    if (!product) {
        showError(`Product ${productCode} not found`);
        return;
    }
    
    showProductDetail(product);
}

function showProductDetail(product) {
    // Update URL with product code
    const params = new URLSearchParams();
    params.set('p', product.productCode);
    if (accumulatedBitValue > 0) {
        params.set('b', accumulatedBitValue.toString());
    }
    
    window.history.pushState(
        { productCode: product.productCode }, 
        '', 
        '?' + params.toString()
    );
    
    // Render product detail
    const compatibleAccessories = accessoryData.filter(acc => 
        product.compatibleAccessories && product.compatibleAccessories.includes(acc.id)
    );
    
    const contentDiv = document.getElementById('content');
    let html = `
        <div class="result-container">
            <div class="result-title">${product.description}</div>
            <div class="result-content">
                <div class="result-details">
                    <p><strong>Product Code:</strong> ${product.productCode}</p>
                    <p><strong>Category:</strong> ${product.category}</p>
                    <p><strong>Base Type:</strong> ${product.baseType || 'N/A'}</p>
                    <p><strong>Materials:</strong> ${product.materials.join(', ') || 'N/A'}</p>
                    <p><strong>Colors:</strong> ${product.colors.join(', ') || 'N/A'}</p>
                    
                    ${compatibleAccessories.length > 0 ? `
                        <h3 style="margin-top: 20px;">Compatible Accessories</h3>
                        <div class="accessories-list">
                            ${compatibleAccessories.map(acc => `
                                <div class="accessory-item">
                                    <strong>${acc.description}</strong><br>
                                    <small>Code: ${acc.accessoryCode} | ${acc.materials.join(', ')}</small>
                                </div>
                            `).join('')}
                        </div>
                    ` : ''}
                </div>
            </div>
            <div class="result-actions">
                <button class="back-button" onclick="goBack()">← Go Back</button>
                <button class="back-button" onclick="startOver()">Start Over</button>
                <button class="back-button" onclick="shareCurrentPage()">🔗 Share Product</button>
            </div>
        </div>
    `;
    
    contentDiv.innerHTML = html;
}
```

### 7. Share Functionality
```javascript
function shareCurrentPage() {
    const url = window.location.href;
    
    if (navigator.clipboard && navigator.clipboard.writeText) {
        navigator.clipboard.writeText(url).then(() => {
            showNotification('Link copied to clipboard!');
        }).catch(() => {
            showUrlPrompt(url);
        });
    } else {
        showUrlPrompt(url);
    }
}

function showUrlPrompt(url) {
    const message = prompt('Copy this URL to share:', url);
}

function showNotification(message) {
    const notification = document.createElement('div');
    notification.className = 'notification';
    notification.textContent = message;
    notification.style.cssText = `
        position: fixed;
        top: 20px;
        right: 20px;
        background: #4CAF50;
        color: white;
        padding: 15px 20px;
        border-radius: 4px;
        box-shadow: 0 2px 8px rgba(0,0,0,0.2);
        z-index: 10000;
        animation: slideIn 0.3s ease-out;
    `;
    
    document.body.appendChild(notification);
    
    setTimeout(() => {
        notification.style.animation = 'slideOut 0.3s ease-in';
        setTimeout(() => notification.remove(), 300);
    }, 3000);
}
```

### 8. Update startOver Function
```javascript
function startOver() {
    history = ['start'];
    
    // Clear all stored answers
    for (const key in userAnswers) {
        delete userAnswers[key];
    }
    
    // Clear bit value
    accumulatedBitValue = 0;
    
    // Clear URL (return to root)
    window.history.replaceState({}, '', window.location.pathname);
    
    loadContent('start');
}
```

### 9. Handle Browser Back Button
```javascript
// Add this to init() or as separate event listener
window.addEventListener('popstate', function(event) {
    if (event.state) {
        if (event.state.productCode) {
            showProductByCode(event.state.productCode);
        } else if (event.state.questionKey) {
            accumulatedBitValue = event.state.bitValue || 0;
            loadContent(event.state.questionKey);
        } else {
            startOver();
        }
    } else {
        // No state, check URL
        initFromURL();
    }
});
```

### 10. Add CSS for Notification
```css
@keyframes slideIn {
    from {
        transform: translateX(400px);
        opacity: 0;
    }
    to {
        transform: translateX(0);
        opacity: 1;
    }
}

@keyframes slideOut {
    from {
        transform: translateX(0);
        opacity: 1;
    }
    to {
        transform: translateX(400px);
        opacity: 0;
    }
}

.accessory-item {
    padding: 10px;
    margin: 5px 0;
    background: #f5f5f5;
    border-left: 3px solid #2196F3;
    border-radius: 3px;
}

.product-card {
    cursor: pointer;
    transition: transform 0.2s, box-shadow 0.2s;
}

.product-card:hover {
    transform: translateY(-2px);
    box-shadow: 0 4px 8px rgba(0,0,0,0.2);
}
```

## Testing Scenarios

### Test 1: Basic Navigation
1. Start quiz
2. Select Door → Storm Door → Aluminum → White
3. Check URL contains `?b=XXXX&q=YYYY`
4. Copy URL
5. Open in new tab → Should restore to same point

### Test 2: Product Deep Link
1. Navigate to product BGIST
2. Check URL contains `?p=BGIST&b=XXXX`
3. Copy URL
4. Open in new tab → Should show product directly

### Test 3: Browser Refresh
1. Navigate through several questions
2. Press F5 to refresh
3. Should restore to same question with selections intact

### Test 4: Browser Back Button
1. Navigate forward through questions
2. Press browser back button
3. Should step backward through questions
4. URL should update accordingly

### Test 5: Share Button
1. Complete navigation flow
2. Click "Share" button
3. Should copy URL to clipboard
4. Paste in new browser → Should restore state

## Benefits

1. **User Experience**: Users don't lose progress on refresh
2. **Shareability**: Users can share specific configurations
3. **Bookmarking**: Useful configurations can be saved
4. **SEO**: Product pages are directly linkable
5. **Analytics**: Track specific navigation paths via URL parameters
6. **Support**: Users can share URLs when asking for help

## URL Encoding Notes

- Bit values are stored as decimal integers (more compact than hex for small values)
- Product codes are URL-safe (no special encoding needed)
- Question IDs are alphanumeric (q-dimensions, etc.)
- Special characters in product codes should be URL-encoded if present
