text: from typing import List, Dict
  from .utils import *
  from .songs import *
  from ytmusicapi.helpers import i18n
  
  
  class Parser:
      def __init__(self, language):
          self.lang = language
  
      @i18n
      def parse_search_results(self, results, resultType=None):
          search_results = []
          default_offset = (not resultType) * 2
          for result in results:
              data = result['musicResponsiveListItemRenderer']
              search_result = {}
              if not resultType:
                  resultType = get_item_text(data, 1).lower()
                  result_types = ['artist', 'playlist', 'song', 'video', 'station']
                  result_types_local = [
                      _('artist'), _('playlist'),
                      _('song'), _('video'),
                      _('station')
                  ]
                  # default to album since it's labeled with multiple values ('Single', 'EP', etc.)
                  if resultType not in result_types_local:
                      resultType = 'album'
                  else:
                      resultType = result_types[result_types_local.index(resultType)]
  
              search_result['resultType'] = resultType
  
              if resultType != 'artist':
                  search_result['title'] = get_item_text(data, 0)
  
              if resultType == 'artist':
                  search_result['artist'] = get_item_text(data, 0)
                  parse_menu_playlists(data, search_result)
  
              elif resultType == 'album':
                  search_result['type'] = get_item_text(data, 1)
  
              elif resultType == 'playlist':
                  search_result['author'] = get_item_text(data, 1, default_offset)
                  search_result['itemCount'] = get_item_text(data, 1,
                                                             default_offset + 2).split('\xa0')[0]
  
              elif resultType == 'station':
                  search_result['videoId'] = nav(data, NAVIGATION_VIDEO_ID)
                  search_result['playlistId'] = nav(data, NAVIGATION_PLAYLIST_ID)
  
              elif resultType == 'song':
                  search_result['duration'] = None
                  search_result['album'] = None
                  if 'menu' in data:
                      toggle_menu = find_object_by_key(nav(data, MENU_ITEMS),
                                                       'toggleMenuServiceItemRenderer')
                      if toggle_menu:
                          search_result['feedbackTokens'] = parse_song_menu_tokens(toggle_menu)
  
              elif resultType == 'video':
                  search_result['views'] = None
  
              elif resultType == 'upload':
                  browse_id = nav(data, NAVIGATION_BROWSE_ID, True)
                  if not browse_id:  # song result
                      flex_items = [
                          nav(get_flex_column_item(data, i), ['text', 'runs'], True)
                          for i in range(2)
                      ]
                      if flex_items[0]:
                          search_result['videoId'] = nav(flex_items[0][0], NAVIGATION_VIDEO_ID)
                          search_result['playlistId'] = nav(flex_items[0][0], NAVIGATION_PLAYLIST_ID)
                      if flex_items[1]:
                          search_result['artist'] = {
                              'name': flex_items[1][0]['text'],
                              'id': nav(flex_items[1][0], NAVIGATION_BROWSE_ID)
                          }
                          search_result['album'] = {
                              'name': flex_items[1][2]['text'],
                              'id': nav(flex_items[1][2], NAVIGATION_BROWSE_ID)
                          }
                          search_result['duration'] = flex_items[1][4]['text']
                      search_result['resultType'] = 'song'
  
                  else:  # artist or album result
                      search_result['browseId'] = browse_id
                      if 'artist' in search_result['browseId']:
                          search_result['resultType'] = 'artist'
                      else:
                          flex_item2 = get_flex_column_item(data, 1)
                          runs = [
                              run['text'] for i, run in enumerate(flex_item2['text']['runs'])
                              if i % 2 == 0
                          ]
                          search_result['artist'] = runs[1]
                          if len(runs) > 2:  # date may be missing
                              search_result['releaseDate'] = runs[2]
                          search_result['resultType'] = 'album'
  
              if resultType in ['song', 'video']:
                  search_result['videoId'] = nav(
                      data, PLAY_BUTTON + ['playNavigationEndpoint', 'watchEndpoint', 'videoId'],
                      True)
  
              if resultType in ['song', 'video', 'album']:
                  search_result['year'] = None
                  song_info = parse_song_runs(get_flex_column_item(data, 1)['text']['runs'])
                  search_result.update(song_info)
  
              if resultType in ['artist', 'album', 'playlist']:
                  search_result['browseId'] = nav(data, NAVIGATION_BROWSE_ID, True)
                  if not search_result['browseId']:
                      continue
  
              if resultType in ['song', 'album']:
                  search_result['isExplicit'] = nav(data, BADGE_LABEL, True) == 'Explicit'
  
              search_result['thumbnails'] = nav(data, THUMBNAILS)
              search_results.append(search_result)
  
          return search_results
  
      @i18n
      def parse_artist_contents(self, results: List) -> Dict:
          categories = ['albums', 'singles', 'videos', 'playlists']
          categories_local = [_('albums'), _('singles'), _('videos'), _('playlists')]
          categories_parser = [parse_album, parse_single, parse_video, parse_playlist]
          artist = {}
          for i, category in enumerate(categories):
              data = [
                  r['musicCarouselShelfRenderer'] for r in results
                  if 'musicCarouselShelfRenderer' in r
                  and nav(r['musicCarouselShelfRenderer'],
                          CAROUSEL_TITLE)['text'].lower() == categories_local[i]
              ]
              if len(data) > 0:
                  artist[category] = {'browseId': None, 'results': []}
                  if 'navigationEndpoint' in nav(data[0], CAROUSEL_TITLE):
                      artist[category]['browseId'] = nav(data[0],
                                                         CAROUSEL_TITLE + NAVIGATION_BROWSE_ID)
                      if category in ['albums', 'singles', 'playlists']:
                          artist[category]['params'] = nav(
                              data[0],
                              CAROUSEL_TITLE)['navigationEndpoint']['browseEndpoint']['params']
  
                  artist[category]['results'] = parse_content_list(data[0]['contents'],
                                                                   categories_parser[i])
  
          return artist
  
  
  def parse_content_list(results, parse_func):
      contents = []
      for result in results:
          contents.append(parse_func(result['musicTwoRowItemRenderer']))
  
      return contents
  
  
  def parse_album(result):
      return {
          'title': nav(result, TITLE_TEXT),
          'year': nav(result, SUBTITLE2, True),
          'browseId': nav(result, TITLE + NAVIGATION_BROWSE_ID),
          'thumbnails': nav(result, THUMBNAIL_RENDERER)
      }
  
  
  def parse_single(result):
      return {
          'title': nav(result, TITLE_TEXT),
          'year': nav(result, SUBTITLE, True),
          'browseId': nav(result, TITLE + NAVIGATION_BROWSE_ID),
          'thumbnails': nav(result, THUMBNAIL_RENDERER)
      }
  
  
  def parse_video(result):
      video = {
          'title': nav(result, TITLE_TEXT),
          'videoId': nav(result, NAVIGATION_VIDEO_ID),
          'playlistId': nav(result, NAVIGATION_PLAYLIST_ID),
          'thumbnails': nav(result, THUMBNAIL_RENDERER)
      }
      if len(result['subtitle']['runs']) == 3:
          video['views'] = nav(result, SUBTITLE2).split(' ')[0]
      return video
  
  
  def parse_playlist(data):
      playlist = {
          'title': nav(data, TITLE_TEXT),
          'playlistId': nav(data, TITLE + NAVIGATION_BROWSE_ID)[2:],
          'thumbnails': nav(data, THUMBNAIL_RENDERER)
      }
      if len(data['subtitle']['runs']) == 3:
          playlist['count'] = nav(data, SUBTITLE2).split(' ')[0]
      return playlist
  