text: from html.parser import HTMLParser
  
  import requests
  from waste_collection_schedule import Collection  # type: ignore[attr-defined]
  from waste_collection_schedule.service.ICS import ICS
  
  TITLE = "Müllmax"
  DESCRIPTION = "Source for Müllmax waste collection."
  URL = "https://www.muellmax.de"
  TEST_CASES = {
      "Rhein-Sieg-Kreis, Alfter": {
          "service": "Rsa",
          "mm_frm_ort_sel": "Alfter",
          "mm_frm_str_sel": "Ahrweg (105-Ende/94-Ende)",
      },
      "Münster, Achatiusweg": {"service": "Awm", "mm_frm_str_sel": "Achatiusweg"},
  }
  
  
  # Parser for HTML checkbox
  class InputCheckboxParser(HTMLParser):
      def __init__(self, startswith):
          super().__init__()
          self._startswith = startswith
          self._value = {}
  
      @property
      def value(self):
          return self._value
  
      def handle_starttag(self, tag, attrs):
          if tag == "input":
              d = dict(attrs)
              if d.get("name", "").startswith(self._startswith):
                  self._value[d["name"]] = d.get("value")
  
  
  # Parser for HTML input (hidden) text
  class InputTextParser(HTMLParser):
      def __init__(self, **identifiers):
          super().__init__()
          self._identifiers = identifiers
          self._value = None
  
      @property
      def value(self):
          return self._value
  
      def handle_starttag(self, tag, attrs):
          if tag == "input":
              d = dict(attrs)
              for key, value in self._identifiers.items():
                  if key not in d or d[key] != value:
                      return
              self._value = d.get("value")
  
  
  class Source:
      def __init__(
          self, service, mm_frm_ort_sel=None, mm_frm_str_sel=None, mm_frm_hnr_sel=None
      ):
          self._service = service
          self._mm_frm_ort_sel = mm_frm_ort_sel
          self._mm_frm_str_sel = mm_frm_str_sel
          self._mm_frm_hnr_sel = mm_frm_hnr_sel
          self._ics = ICS()
  
      def fetch(self):
          mm_ses = InputTextParser(name="mm_ses")
  
          url = f"https://www.muellmax.de/abfallkalender/{self._service.lower()}/res/{self._service}Start.php"
          r = requests.get(url)
          mm_ses.feed(r.text)
  
          # select "Abfuhrtermine", returns ort or an empty street search field
          args = {"mm_ses": mm_ses.value, "mm_aus_ort.x": 0, "mm_aus_ort.x": 0}
          r = requests.post(url, data=args)
          mm_ses.feed(r.text)
  
          if self._mm_frm_ort_sel is not None:
              # select city
              args = {
                  "mm_ses": mm_ses.value,
                  "xxx": 1,
                  "mm_frm_ort_sel": self._mm_frm_ort_sel,
                  "mm_aus_ort_submit": "weiter",
              }
              r = requests.post(url, data=args)
              mm_ses.feed(r.text)
  
          if self._mm_frm_str_sel is not None:
              # show street selection page
              args = {
                  "mm_ses": mm_ses.value,
                  "xxx": 1,
                  "mm_frm_str_name": "",
                  "mm_aus_str_txt_submit": "suchen",
              }
              r = requests.post(url, data=args)
              mm_ses.feed(r.text)
  
              # select street
              args = {
                  "mm_ses": mm_ses.value,
                  "xxx": 1,
                  "mm_frm_str_sel": self._mm_frm_str_sel,
                  "mm_aus_str_sel_submit": "weiter",
              }
              r = requests.post(url, data=args)
              mm_ses.feed(r.text)
  
          if self._mm_frm_hnr_sel is not None:
              # select house number
              args = {
                  "mm_ses": mm_ses.value,
                  "xxx": 1,
                  "mm_frm_hnr_sel": self._mm_frm_hnr_sel,
                  "mm_aus_hnr_sel_submit": "weiter",
              }
              r = requests.post(url, data=args)
              mm_ses.feed(r.text)
  
          # select to get ical
          args = {"mm_ses": mm_ses.value, "xxx": 1, "mm_ica_auswahl": "iCalendar-Datei"}
          r = requests.post(url, data=args)
          mm_ses.feed(r.text)
  
          mm_frm_fra = InputCheckboxParser(startswith="mm_frm_fra")
          mm_frm_fra.feed(r.text)
  
          # get ics file
          args = {"mm_ses": mm_ses.value, "xxx": 1, "mm_frm_type": "termine"}
          args.update(mm_frm_fra.value)
          args.update({"mm_ica_gen": "iCalendar-Datei laden"})
          r = requests.post(url, data=args)
          mm_ses.feed(r.text)
  
          entries = []
  
          # parse ics file
          dates = self._ics.convert(r.text)
  
          entries = []
          for d in dates:
              entries.append(Collection(d[0], d[1]))
          return entries
  