content: sub init()
      m.log = log_Logger("ServerDiscoveryTask")
      m.top.functionName = "execute"
  end sub
  
  sub execute()
      m.servers = []
      m.serverUrlMap = {}
      m.locationUrlMap = {}
  
      ' Adicionar o servidor pré-definido
      AddPredefinedServer()
  
      SendSSDPBroadcast()
      SendClientDiscoveryBroadcast()
      ts = CreateObject("roTimespan")
      maxTimeMs = 2200
  
      while True
          elapsed = ts.TotalMilliseconds()
          if elapsed >= maxTimeMs
              exit while
          end if
          msg = Wait(100, m.ssdp.port)
          if msg <> invalid
              ProcessSSDPResponse(msg)
          end if
          msg = Wait(100, m.clientDiscovery.port)
          if msg <> invalid
              ProcessClientDiscoveryResponse(msg)
          end if
      end while
      m.top.content = m.servers
      
  end sub
  
  sub AddServer(server)
      if m.serverUrlMap[server.baseUrl] = invalid
          m.serverUrlMap[server.baseUrl] = true
          m.servers.push(server)
      end if
  end sub
  
  sub AddPredefinedServer()
      predefinedServer = {
          name: "Servidor Padrão"
          baseUrl: "http://192.168.4.14:8025"
          iconUrl: "pkg:/images/logo-icon120.jpg" ' Ícone padrão
          iconWidth: 120
          iconHeight: 120
      }
      AddServer(predefinedServer)
  end sub
  
  sub SendClientDiscoveryBroadcast()
      m.clientDiscovery = {
          port: CreateObject("roMessagePort")
          address: CreateObject("roSocketAddress")
          socket: CreateObject("roDatagramSocket")
          urlTransfer: CreateObject("roUrlTransfer")
      }
      m.clientDiscovery.address.SetAddress("255.255.255.255:7359")
      m.clientDiscovery.urlTransfer.SetPort(m.clientDiscoveryPort)
      m.clientDiscovery.socket.SetMessagePort(m.clientDiscovery.port)
      m.clientDiscovery.socket.SetSendToAddress(m.clientDiscovery.address)
      m.clientDiscovery.socket.NotifyReadable(true)
      m.clientDiscovery.socket.SetBroadcast(true)
      m.clientDiscovery.socket.SendStr("Who is JellyfinServer?")
  end sub
  
  sub ProcessClientDiscoveryResponse(message)
      if Type(message) = "roSocketEvent" and message.GetSocketId() = m.clientDiscovery.socket.GetId() and m.clientDiscovery.socket.IsReadable()
          try
              responseJson = m.clientDiscovery.socket.ReceiveStr(4096)
              server = ParseJson(responseJson)
              AddServer({
                  name: server.Name
                  baseUrl: server.Address
  
                  iconUrl: "pkg:/images/logo-icon120.jpg"
                  iconWidth: 120
                  iconHeight: 120
              })
              
          catch e
              
          end try
      end if
  end sub
  
  sub SendSSDPBroadcast()
      m.ssdp = {
          port: CreateObject("roMessagePort")
          address: CreateObject("roSocketAddress")
          socket: CreateObject("roDatagramSocket")
          urlTransfer: CreateObject("roUrlTransfer")
      }
      m.ssdp.address.SetAddress("239.255.255.250:1900")
      m.ssdp.socket.SetMessagePort(m.ssdp.port)
      m.ssdp.socket.SetSendToAddress(m.ssdp.address)
      m.ssdp.socket.NotifyReadable(true)
      m.ssdp.urlTransfer.SetPort(m.ssdp.port)
  
      Q = Chr(34)
      CRLF = Chr(13) + Chr(10)
      ssdpStr = "M-SEARCH * HTTP/1.1" + CRLF
      ssdpStr += "HOST: 239.255.255.250:1900" + CRLF
      ssdpStr += "MAN: " + Q + "ssdp:discover" + Q + CRLF
      ssdpStr += "ST:urn:schemas-upnp-org:device:MediaServer:1" + CRLF
      ssdpStr += "MX: 2" + CRLF
      ssdpStr += CRLF
      m.ssdp.socket.SendStr(ssdpStr)
  end sub
  
  sub ProcessSSDPResponse(message)
      locationUrl = invalid
      if Type(message) = "roSocketEvent" and message.GetSocketId() = m.ssdp.socket.GetId() and m.ssdp.socket.IsReadable()
          recvStr = m.ssdp.socket.ReceiveStr(4096)
          match = CreateObject("roRegex", "\r\nLocation:\s*(.*?)\s*\r\n", "i").Match(recvStr)
          if match.Count() = 2
              locationUrl = match[1]
          end if
      end if
      if locationUrl = invalid
          return
      else if m.locationUrlMap[locationUrl] <> invalid
          
          return
      end if
      m.locationUrlMap[locationUrl] = true
      http = CreateObject("roUrlTransfer")
      http.SetUrl(locationUrl)
      responseText = http.GetToString()
      xml = CreateObject("roXMLElement")
  
      if xml.Parse(responseText)
          deviceNode = xml.GetNamedElementsCi("device")[0]
          manufacturer = deviceNode.GetNamedElementsCi("manufacturer").GetText()
  
          if lcase(manufacturer) = "jellyfin"
  
              width = 0
              server = invalid
              icons = deviceNode.GetNamedElementsCi("iconList")[0].GetNamedElementsCi("icon")
              for each iconNode in icons
                  iconUrl = iconNode.GetNamedElementsCi("url").GetText()
                  baseUrl = invalid
                  match = CreateObject("roRegex", "(.*?)\/dlna\/", "i").Match(iconUrl)
                  if match.Count() = 2
                      baseUrl = match[1]
                  end if
                  loopResult = {
                      name: deviceNode.GetNamedElementsCi("friendlyName").GetText()
                      baseUrl: baseUrl
                      iconUrl: iconUrl
                      iconWidth: iconNode.GetNamedElementsCi("width")[0].GetText().ToInt()
                      iconHeight: iconNode.GetNamedElementsCi("height")[0].GetText().ToInt()
                  }
                  if baseUrl <> invalid and loopResult.iconWidth > width
                      width = loopResult.iconWidth
                      server = loopResult
                  end if
              end for
              AddServer(server)
              
          end if
      end if
  end sub
  