# Vue.js Media Transformer - Všechny varianty implementace

## 1. Composable (Vue 3 Composition API)

```javascript
// composables/useMediaObjects.js
export function useMediaObjects() {
  const transformMediaObjects = (productGallery, productVideos) => {
    const finalObjects = []

    // Photos
    if (productGallery) {
      finalObjects.push(
        ...productGallery.map((photo, index) => ({
          ...photo,
          type: 'photo',
          rank: index + 1
        }))
      )
    }

    // Videos
    if (productVideos) {
      finalObjects.push(
        ...productVideos.map((videoUrl, index) => {
          const youtubeId = extractYouTubeId(videoUrl)
          return {
            url: videoUrl,
            type: 'video',
            rank: finalObjects.length + index + 1,
            previewThumb: youtubeId 
              ? `https://img.youtube.com/vi/${youtubeId}/sddefault.jpg` 
              : null
          }
        })
      )
    }

    return finalObjects
  }

  const extractYouTubeId = (url) => {
    return url.match(
      /(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/\s]{11})/
    )?.[1]
  }

  return {
    transformMediaObjects,
    extractYouTubeId
  }
}
```

### Použití v komponentě:
```javascript
// Product.vue
<script setup>
import { computed } from 'vue'
import { useMediaObjects } from '@/composables/useMediaObjects'

const props = defineProps(['productGallery', 'product'])

const { transformMediaObjects } = useMediaObjects()

const mediaObjects = computed(() => {
  return transformMediaObjects(props.productGallery, props.product?.product_video)
})
</script>
```

## 2. JS Třída - Statické metody

```javascript
// services/MediaTransformer.js
export class MediaTransformer {
  static transform(productGallery, productVideos) {
    const finalObjects = []

    if (productGallery) {
      finalObjects.push(
        ...productGallery.map((photo, index) => ({
          ...photo,
          type: 'photo',
          rank: index + 1
        }))
      )
    }

    if (productVideos) {
      finalObjects.push(
        ...productVideos.map((videoUrl, index) => {
          const youtubeId = this.extractYouTubeId(videoUrl)
          return {
            url: videoUrl,
            type: 'video',
            rank: finalObjects.length + index + 1,
            previewThumb: youtubeId 
              ? `https://img.youtube.com/vi/${youtubeId}/sddefault.jpg` 
              : null
          }
        })
      )
    }

    return finalObjects
  }

  static extractYouTubeId(url) {
    return url.match(
      /(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/\s]{11})/
    )?.[1]
  }

  static generateThumbnail(youtubeId, quality = 'sddefault') {
    return `https://img.youtube.com/vi/${youtubeId}/${quality}.jpg`
  }
}
```

### Použití:
```javascript
// Product.vue
<script setup>
import { computed } from 'vue'
import { MediaTransformer } from '@/services/MediaTransformer'

const props = defineProps(['productGallery', 'product'])

const mediaObjects = computed(() => {
  return MediaTransformer.transform(props.productGallery, props.product?.product_video)
})
</script>
```

## 3. JS Třída - Export třídy (instance v komponentě)

```javascript
// services/MediaTransformer.js
export class MediaTransformer {
  constructor(config = {}) {
    this.thumbnailQuality = config.thumbnailQuality || 'sddefault'
    this.defaultVideoType = config.defaultVideoType || 'video'
  }

  transform(productGallery, productVideos) {
    const finalObjects = []

    if (productGallery) {
      finalObjects.push(
        ...productGallery.map((photo, index) => ({
          ...photo,
          type: 'photo',
          rank: index + 1
        }))
      )
    }

    if (productVideos) {
      finalObjects.push(
        ...productVideos.map((videoUrl, index) => {
          const youtubeId = this.extractYouTubeId(videoUrl)
          return {
            url: videoUrl,
            type: this.defaultVideoType,
            rank: finalObjects.length + index + 1,
            previewThumb: youtubeId 
              ? `https://img.youtube.com/vi/${youtubeId}/${this.thumbnailQuality}.jpg` 
              : null
          }
        })
      )
    }

    return finalObjects
  }

  extractYouTubeId(url) {
    return url.match(
      /(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/\s]{11})/
    )?.[1]
  }

  setConfig(newConfig) {
    Object.assign(this, newConfig)
    return this
  }
}
```

### Použití:
```javascript
// Product.vue
<script setup>
import { computed, ref } from 'vue'
import { MediaTransformer } from '@/services/MediaTransformer'

const props = defineProps(['productGallery', 'product'])

const mediaTransformer = ref(new MediaTransformer({ thumbnailQuality: 'hqdefault' }))

const mediaObjects = computed(() => {
  return mediaTransformer.value.transform(props.productGallery, props.product?.product_video)
})
</script>
```

## 4. JS Třída - Export instance (singleton)

```javascript
// services/MediaTransformer.js
class MediaTransformer {
  constructor(config = {}) {
    this.thumbnailQuality = config.thumbnailQuality || 'sddefault'
  }

  transform(productGallery, productVideos) {
    // stejná implementace jako výše...
  }

  extractYouTubeId(url) {
    // stejná implementace...
  }

  setConfig(newConfig) {
    Object.assign(this, newConfig)
    return this
  }
}

// Export instance
export const mediaTransformer = new MediaTransformer()

// Případně export obou
export { MediaTransformer }
```

### Použití:
```javascript
// Product.vue
<script setup>
import { computed } from 'vue'
import { mediaTransformer } from '@/services/MediaTransformer'

const props = defineProps(['productGallery', 'product'])

const mediaObjects = computed(() => {
  return mediaTransformer.transform(props.productGallery, props.product?.product_video)
})

// Změna konfigurace kdykoliv:
// mediaTransformer.setConfig({ thumbnailQuality: 'maxresdefault' })
</script>
```

## 5. Singleton Pattern

```javascript
// services/MediaTransformer.js
class MediaTransformer {
  static _instance = null
  
  constructor(config = {}) {
    if (MediaTransformer._instance) {
      return MediaTransformer._instance
    }
    
    this.thumbnailQuality = config.thumbnailQuality || 'sddefault'
    MediaTransformer._instance = this
  }
  
  static getInstance(config = {}) {
    if (!this._instance) {
      this._instance = new MediaTransformer(config)
    }
    return this._instance
  }

  transform(productGallery, productVideos) {
    // implementace...
  }

  extractYouTubeId(url) {
    // implementace...
  }
}

export default MediaTransformer
```

### Použití:
```javascript
// Product.vue
<script setup>
import { computed } from 'vue'
import MediaTransformer from '@/services/MediaTransformer'

const props = defineProps(['productGallery', 'product'])

const mediaObjects = computed(() => {
  const transformer = MediaTransformer.getInstance({ thumbnailQuality: 'hqdefault' })
  return transformer.transform(props.productGallery, props.product?.product_video)
})
</script>
```

## 6. Factory Function

```javascript
// services/MediaTransformer.js
class MediaTransformer {
  constructor(config = {}) {
    this.thumbnailQuality = config.thumbnailQuality || 'sddefault'
  }

  transform(productGallery, productVideos) {
    // implementace...
  }

  extractYouTubeId(url) {
    // implementace...
  }
}

export const createMediaTransformer = (config = {}) => {
  return new MediaTransformer(config)
}

// Export i třídy pro pokročilé použití
export { MediaTransformer }
```

### Použití:
```javascript
// Product.vue
<script setup>
import { computed, ref } from 'vue'
import { createMediaTransformer } from '@/services/MediaTransformer'

const props = defineProps(['productGallery', 'product'])

const mediaTransformer = ref(createMediaTransformer({ thumbnailQuality: 'maxresdefault' }))

const mediaObjects = computed(() => {
  return mediaTransformer.value.transform(props.productGallery, props.product?.product_video)
})
</script>
```

## 7. Plain Object/Service

```javascript
// services/mediaService.js
export const mediaService = {
  defaultConfig: {
    thumbnailQuality: 'sddefault'
  },

  transform(productGallery, productVideos, config = {}) {
    const finalConfig = { ...this.defaultConfig, ...config }
    const finalObjects = []

    if (productGallery) {
      finalObjects.push(
        ...productGallery.map((photo, index) => ({
          ...photo,
          type: 'photo',
          rank: index + 1
        }))
      )
    }

    if (productVideos) {
      finalObjects.push(
        ...productVideos.map((videoUrl, index) => {
          const youtubeId = this.extractYouTubeId(videoUrl)
          return {
            url: videoUrl,
            type: 'video',
            rank: finalObjects.length + index + 1,
            previewThumb: youtubeId 
              ? `https://img.youtube.com/vi/${youtubeId}/${finalConfig.thumbnailQuality}.jpg` 
              : null
          }
        })
      )
    }

    return finalObjects
  },

  extractYouTubeId(url) {
    return url.match(
      /(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/\s]{11})/
    )?.[1]
  }
}
```

### Použití:
```javascript
// Product.vue
<script setup>
import { computed } from 'vue'
import { mediaService } from '@/services/mediaService'

const props = defineProps(['productGallery', 'product'])

const mediaObjects = computed(() => {
  return mediaService.transform(
    props.productGallery, 
    props.product?.product_video,
    { thumbnailQuality: 'hqdefault' }
  )
})
</script>
```

## 8. Pure Functions (Helper)

```javascript
// utils/mediaTransform.js
export const transformMediaObjects = (productGallery, productVideos, config = {}) => {
  const { thumbnailQuality = 'sddefault' } = config
  const finalObjects = []

  if (productGallery) {
    finalObjects.push(
      ...productGallery.map((photo, index) => ({
        ...photo,
        type: 'photo',
        rank: index + 1
      }))
    )
  }

  if (productVideos) {
    finalObjects.push(
      ...productVideos.map((videoUrl, index) => {
        const youtubeId = extractYouTubeId(videoUrl)
        return {
          url: videoUrl,
          type: 'video',
          rank: finalObjects.length + index + 1,
          previewThumb: youtubeId 
            ? `https://img.youtube.com/vi/${youtubeId}/${thumbnailQuality}.jpg` 
            : null
        }
      })
    )
  }

  return finalObjects
}

export const extractYouTubeId = (url) => {
  return url.match(
    /(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/\s]{11})/
  )?.[1]
}
```

### Použití:
```javascript
// Product.vue
<script setup>
import { computed } from 'vue'
import { transformMediaObjects } from '@/utils/mediaTransform'

const props = defineProps(['productGallery', 'product'])

const mediaObjects = computed(() => {
  return transformMediaObjects(
    props.productGallery, 
    props.product?.product_video,
    { thumbnailQuality: 'hqdefault' }
  )
})
</script>
```

---

## Srovnání variant

| Varianta | Výhody | Nevýhody | Použití |
|----------|--------|----------|---------|
| **Composable** | Vue 3 native, reaktivita, auto-import | Vue specific | Vue 3 projekty |
| **Statické metody** | Jednoduché, žádná konfigurace | Není flexibilní | Jednoduché transformace |
| **Export třídy** | Flexibilní konfigurace | Musíš vytvářet instance | Různé konfigurace |
| **Export instance** | Žádné `new`, sdílený stav | Pevná konfigurace | Jednotná konfigurace |
| **Singleton** | Jedna instance, lazy loading | Složitější pattern | Globální konfigurace |
| **Factory** | Flexibilní vytváření | Extra abstrakce | Komplexní objekty |
| **Plain Object** | Jednoduché, framework agnostic | Není OOP | Malé utility |
| **Pure Functions** | Nejjednodušší, testovatelné | Žádná organizace | Funkcionální přístup |

## Doporučení

- **Pro jednoduché transformace**: Pure Functions nebo Statické metody
- **Pro flexibilní konfiguraci**: Export třídy nebo Factory
- **Pro Vue 3 projekty**: Composable
- **Pro globální použití**: Export instance s `setConfig`