text: """Write report about a RINEX navigation file analysis run
  
  Description:
  ------------
  
  asdf
  
  
  """
  # Standard library imports
  from datetime import datetime
  from typing import Tuple
  
  # External library imports
  import pandas as pd
  
  # Midgard imports
  from midgard.collections import enums
  from midgard.dev import plugins
  from midgard.plot.matplotlib_extension import plot_bar_dataframe_columns
  
  # Where imports
  from where.lib import config
  from where.writers._gnss_plot import GnssPlot
  from where.writers._report import Report
  
  
  FIGURE_DPI = 200
  FIGURE_FORMAT = "png"
  
  
  @plugins.register
  def rinex_nav_report(dset: "Dataset") -> None:
      """Write report about a RINEX navigation file analysis run
  
      Args:
          dset:        A dataset containing the data.
      """
      file_vars = {**dset.vars, **dset.analysis}
  
      # TODO: Better solution?
      if "station" not in file_vars:  # necessary if called for example by ./where/tools/concatenate.py
          file_vars["station"] = ""
          file_vars["STATION"] = ""
  
      # Generate figure directory to save figures generated for RINEX navigation file report
      figure_dir = config.files.path("output_rinex_nav_report_figure", file_vars=file_vars)
      figure_dir.mkdir(parents=True, exist_ok=True)
  
      # Generate RINEX navigation file report
      path = config.files.path("output_rinex_nav_report", file_vars=file_vars)
      with config.files.open_path(path, create_dirs=True, mode="wt") as fid:
          rpt = Report(fid, rundate=dset.analysis["rundate"], path=path, description="RINEX navigation file analysis")
          rpt.title_page()
          rpt.write_config()
          _add_figures(dset, rpt, figure_dir)
          _add_tables(dset, rpt, figure_dir)
          rpt.markdown_to_pdf()
  
  
  def _add_figures(dset: "Dataset", rpt: "Report", figure_dir: "pathlib.PosixPath") -> None:
      """Add figures to report
  
      Args:
          dset:        A dataset containing the data.
          rpt:         Report object.
          figure_dir:  Figure directory.
      """
      rpt.add_text("\n# GNSS signal-in-space (SIS) status\n\n")
      plt = GnssPlot(dset, figure_dir, figure_format=FIGURE_FORMAT)
  
      # Plot GNSS SIS status (except if only Galileo system is available)
      if not (len(dset.unique("system")) == 1 and dset.unique("system")[0] == "E"):
          caption = "GNSS signal-in-space (SIS) status for each navigation message."
          if "E" in dset.unique("system"):  # Add extra comment for Galileo
              signal, nav_type = plt.get_first_galileo_signal()
              caption += (
                  f" Galileo SIS status is given for signal '{signal.upper()}' and "
                  f"navigation message type '{nav_type}'."
              )
          rpt.add_figure(
                  figure_path=plt.plot_gnss_signal_in_space_status_overview(), 
                  caption=caption, 
                  clearpage=True,
          )
  
      # Plots are only generated for Galileo
      for figure_path in plt.plot_gnss_signal_in_space_status():
          gnss = figure_path.stem.split("_")[5]
          if gnss == "galileo":
              caption=f"Galileo signal-in-space (SIS) status for signal {figure_path.stem.split('_')[-1].upper()}"
          else:
              caption=f"{gnss.upper()} signal-in-space (SIS) status"
              
          rpt.add_figure(
                  figure_path=figure_path, 
                  caption=caption, 
          )
          
      rpt.add_text("\n\\clearpage\n\n")
  
  
  def _add_tables(dset: "Dataset", rpt: "Report", figure_dir: "pathlib.PosixPath") -> None:
      """Add tables and related plots to report
  
      Args:
          dset:        A dataset containing the data.
          rpt:         Report object.
          figure_dir:  Figure directory.
      """
  
      rpt.add_text("\n# Number of GNSS navigation messages\n\n")
  
      # Generate tables
      df = _table_navigation_message_overview(dset)
      rpt.write_dataframe_to_markdown(df, format="6.0f")
  
      # Plot GNSS navigation message overview (except if only Galileo system is available)
      if not (len(dset.unique("system")) == 1 and dset.unique("system")[0] == "E"):
          path = figure_dir / f"plot_bar_navigation_num_msg.{FIGURE_FORMAT}"
          plot_bar_dataframe_columns(
              df,
              column="num_msg",
              path=path,
              xlabel="Satellite",
              ylabel="Number of navigation messages",
              opt_args={"colormap": "viridis", "figsize": (15, 10), "fontsize": 16},
          )
          rpt.add_figure(path, "Number of navigation messages for each GNSS satellite.")
  
      # Plot Galileo navigation message overviews
      if "E" in dset.unique("system"):
          ylabel = {
              "fnav": "Number of F/NAV navigation messages",
              "inav": "Number of I/NAV navigation messages",
              "inav_e1": "Number of I/NAV navigation messages\ntransmitted by E1 signal",
              "inav_e5b": "Number of I/NAV navigation messages\ntransmitted by E5b signal",
              "inav_e1e5b": "Number of I/NAV navigation messages\ntransmitted by E1/E5b signal",
          }
  
          df_galileo = df[df["label"] == "Galileo"]  # Keep only Galileo observations
          df_galileo = df_galileo.drop(columns=["label"])  # Drop label column -> otherwise legend is plotted
  
          for column in ylabel.keys():
              if sum(df[column]) == 0:  # Skip plotting
                  continue
              path = figure_dir / f"plot_bar_navigation_{column}.{FIGURE_FORMAT}"
              plot_bar_dataframe_columns(df_galileo, column=column, path=path, xlabel="Satellite", ylabel=ylabel[column])
              rpt.add_figure(path, f"{ylabel[column]} for each satellite.")
  
  
  #
  # TABLE GENERATION FUNCTIONS
  #
  def _table_navigation_message_overview(dset: "Dataset"):
      """Generate Dataframe table with overview over number of navigation messages
  
      Args:
          dset:      A dataset containing the data.
  
      Returns:
          Dataframe with satellites as indices and following columns:
  
          | Name        | Description                                                                                  |
          |-------------|----------------------------------------------------------------------------------------------|
          | num_msg     | Number of navigation messages for each satellite                                             |
          | fnav        | Number of Galileo F/NAV navigation messages for each satellite                               |
          | inav        | Number of Galileo F/NAV navigation messages for each satellite                               |
          | inav_e1     | Number of Galileo I/NAV navigation messages transmitted by E1 signal for each satellite      |
          | inav_e5b    | Number of Galileo I/NAV navigation messages transmitted by E5b signal for each satellite     |
          | inav_e1e5b  | Number of Galileo merged I/NAV navigation messages transmitted by E1 and E5b signal for each |
          |             | satellite                                                                                    |
  
          Example:
  
              |    |num_msg| fnav| inav| inav_e1| inav_e5b| inav_e1e5b|
              |----|-------|-----|-----|--------|---------|-----------|
              | C01|     72|    0|    0|       0|        0|          0|
              | C02|     72|    0|    0|       0|        0|          0|
              | .. |    ...|  ...|  ...|     ...|      ...|        ...|
              | E01|    637|  159|  478|     160|      159|        159|
              | E02|    615|  155|  460|     155|      150|        155|
              | .. |    ...|  ...|  ...|     ...|      ...|        ...|
  
      """
      df = dset.as_dataframe()
  
      # Keep only data for run date
      day_start, day_end = _get_day_limits(dset)
      df = df[(df.time >= day_start) & (df.time <= day_end)]
  
      # Generate dataframe table with overview over number of navigation messages
      columns = ["label", "num_msg", "fnav", "inav", "inav_e1", "inav_e5b", "inav_e1e5b"]
      df_nav = pd.DataFrame(columns=columns)
      for satellite in sorted(dset.unique("satellite")):
  
          label = enums.gnss_id_to_name[satellite[0]].value  # GNSS identifier used as label
          num_msg = len(df.query(f"satellite == '{satellite}'"))
          fnav = len(df.query(f"satellite == '{satellite}' and nav_type == 'FNAV_E5a'"))
          inav_e1 = len(df.query(f"satellite == '{satellite}' and nav_type == 'INAV_E1'"))
          inav_e5b = len(df.query(f"satellite == '{satellite}' and nav_type == 'INAV_E5b'"))
          inav_e1e5b = len(df.query(f"satellite == '{satellite}' and nav_type == 'INAV_E1E5b'"))
          inav = inav_e1 + inav_e5b + inav_e1e5b
  
          row = [label, num_msg, fnav, inav, inav_e1, inav_e5b, inav_e1e5b]
          df_nav = df_nav.append(pd.DataFrame([row], columns=columns, index=[satellite]))
  
      return df_nav
  
  
  #        
  # AUXILIARY FUNCTIONS
  # 
  def _get_day_limits(dset: "Dataset") -> Tuple[datetime, datetime]:
      """Get start and end time for given run date
  
          Args:
              dset:      A dataset containing the data.
  
          Returns:
              Start and end date. 
          """
      day_start = min(dset.time.datetime)
      day_end = max(dset.time.datetime)
  
      return day_start, day_end