//
// Copyright (c) Double Symmetry GmbH
// Commercial use requires a license. See https://rntp.dev/pricing
//

import Foundation

/// Maps a decoded ICY metadata block to `StreamMetadata`.
enum ICYMetadataParser {

  /// Returns `nil` when the block has no user-visible fields.
  static func streamMetadata(from block: String) -> StreamMetadata? {
    var title: String?
    var artist: String?
    var artworkUri: String?

    let f = fields(in: block)
    if let streamTitle = f["streamtitle"] {
      let parsed = AVPlayerEngine.parseStreamTitle(streamTitle)
      title = parsed.title
      artist = parsed.artist
    }
    if let streamUrl = f["streamurl"], !streamUrl.isEmpty {
      artworkUri = streamUrl
    }

    let metadata = StreamMetadata(
      title: title,
      artist: artist,
      albumTitle: nil,
      artworkUri: artworkUri,
      genre: nil
    )
    return metadata.isEmpty ? nil : metadata
  }

  /// Parse fields left-to-right so key-like text inside a value is not matched.
  private static func fields(in block: String) -> [String: String] {
    var result: [String: String] = [:]
    var idx = block.startIndex
    while idx < block.endIndex {
      guard let eq = block.range(of: "='", range: idx..<block.endIndex) else { break }
      let key = String(block[idx..<eq.lowerBound]).lowercased()
      let valueStart = eq.upperBound
      let value: String
      let nextIdx: String.Index
      if let terminator = block.range(of: "';", range: valueStart..<block.endIndex) {
        value = String(block[valueStart..<terminator.lowerBound])
        nextIdx = terminator.upperBound
      } else {
        var rest = block[valueStart..<block.endIndex]
        if rest.hasSuffix("'") { rest = rest.dropLast() }
        value = String(rest)
        nextIdx = block.endIndex
      }
      if result[key] == nil { result[key] = value }
      idx = nextIdx
    }
    return result
  }
}
