{
  config,
  lib,
  pkgs,
  ...
}:
let
  inherit (lib)
    mkIf
    mkEnableOption
    mkPackageOption
    mkOption
    ;

  cfg = config.programs.pyradio;
in
{
  meta.maintainers = with lib.maintainers; [ magicquark ];

  options.programs.pyradio = {
    enable = mkEnableOption "pyradio";

    package = mkPackageOption pkgs "pyradio" { nullable = true; };

    settings = mkOption {
      type =
        with lib.types;
        attrsOf (oneOf [
          str
          int
          bool
        ]);
      default = { };
      example = {
        enable_clock = true;
        enable_notifications = 0;
        player = "mpv";
        theme = "dark_16_colors";
        time_format = 0;
        use_transparency = true;
      };
      description = ''
        Options to add to the PyRadio {file}`config` file.
        See <https://github.com/coderholic/pyradio/blob/master/pyradio/config>
        for available options.
      '';
    };

    stations = mkOption {
      type =
        with lib.types;
        listOf (submodule {
          options = {
            name = mkOption {
              type = str;
              description = "Display name of the radio station.";
            };

            url = mkOption {
              type = str;
              description = "Stream URL of the radio station.";
            };

            buffering = mkOption {
              type = nullOr (submodule {
                options = {
                  seconds = mkOption {
                    type = ints.positive;
                    description = "Number of seconds to buffer the stream.";
                  };
                  bitrate = mkOption {
                    type = ints.positive;
                    default = 128;
                    description = "Bitrate of the stream in kbps (modify only if using MPlayer).";
                  };
                };
              });
              description = "Buffering configuration to apply to the station.";
              default = null;
            };

            encoding = mkOption {
              type = str;
              default = "";
              description = "Encoding of the station's metadata block.";
            };

            forceHttp = mkOption {
              type = bool;
              default = false;
              description = "If enabled, the connection is forced to use http (note when false it can either use http or https).";
            };

            iconUrl = mkOption {
              type = str;
              default = "";
              description = "URL of an icon to be shown in desktop notifications.";
            };

            profile = mkOption {
              type = str;
              default = "";
              description = "Name of the profile to use when using mpv or mplayer.";
            };

            volume = mkOption {
              type = ints.between 0 130;
              default = 50;
              description = "Volume to use for the station.";
            };
          };
        });
      default = [ ];
      example = [
        {
          name = "DEF CON Radio (SomaFM)";
          url = "https://somafm.com/defcon256.pls";
        }
        {
          name = "Intense Radio - We Love Dance!";
          url = "https://secure.live-streams.nl/flac.ogg";
        }
      ];
      description = ''
        Radio stations to add to the {file}`stations.csv` file.
        If empty, {file}`stations.csv` defaults to the built-in playlist.

        To add a group, add a station with the url set to "-" and the name set
        to the name of the group. Its order in the list will be where it appears
        in `pyradio`.
      '';
    };
  };

  config = mkIf cfg.enable {
    home.packages = mkIf (cfg.package != null) [ cfg.package ];

    xdg.configFile."pyradio/config" = mkIf (cfg.settings != { }) {
      text =
        let
          renderedSettings = lib.generators.toINIWithGlobalSection { } {
            globalSection = cfg.settings;
          };
        in
        lib.removeSuffix "\n\n" ''
          # Generated by Home Manager.

          ${renderedSettings}
        '';
    };

    xdg.configFile."pyradio/stations.csv" = mkIf (cfg.stations != [ ]) {
      text =
        let
          escapeCSV =
            s:
            if lib.hasInfix "," s || lib.hasInfix "\"" s then
              "\"${lib.replaceStrings [ "\"" ] [ "\"\"" ] s}\""
            else
              s;

          stationsToCSV =
            stations:
            let
              body = lib.concatMapStringsSep "\n" (
                station:
                lib.concatStringsSep "," [
                  (escapeCSV station.name)
                  (escapeCSV station.url)
                  station.encoding
                  (escapeCSV station.iconUrl)
                  (escapeCSV station.profile)
                  (lib.optionalString (
                    station.buffering != null
                  ) "${toString station.buffering.seconds}@${toString station.buffering.bitrate}")
                  (if station.forceHttp then "1" else "0")
                  (toString station.volume)
                ]
              ) stations;
            in
            "${body}\n";
        in
        stationsToCSV cfg.stations;
    };
  };
}
