{
  config,
  lib,
  pkgs,
  ...
}:

let
  settings_format = pkgs.formats.json { };
  waybar_config_json = settings_format.generate "config" config.me.waybar.config;
  launch_waybar = pkgs.writeShellScript "launch_waybar" ''
    exec waybar --config '${waybar_config_json}' --style '${./files/style.css}'
  '';
  waybar_sway_config = pkgs.writeTextFile {
    name = "waybar.conf";
    text = ''
      #
      # Status Bar:
      #
      # Read `man 5 sway-bar` for more information about this section.
      bar {
          position top

          font pango:Cascadia Mono, FontAwesome 10
          swaybar_command ${launch_waybar}

          colors {
              statusline #ffffff
              background #323232
              inactive_workspace #32323200 #32323200 #5c5c5c
          }
      }
    '';
  };

  patchScriptBin =
    filename: contents:
    ((pkgs.writeScriptBin filename contents).overrideAttrs (old: {
      buildCommand = "${old.buildCommand}\n patchShebangs $out";
    }));
  waybar_available_memory = (
    patchScriptBin "waybar_custom_available_memory" (
      builtins.readFile ./files/waybar_scripts/waybar_available_memory_linux.bash
    )
  );
  waybar_battery = (
    patchScriptBin "waybar_custom_battery" (
      builtins.readFile ./files/waybar_scripts/waybar_battery_linux.bash
    )
  );
  waybar_clock = (
    patchScriptBin "waybar_custom_clock" (
      builtins.readFile ./files/waybar_scripts/waybar_custom_clock.py
    )
  );
  waybar_night_mode = (
    patchScriptBin "waybar_night_mode" (builtins.readFile ./files/waybar_scripts/waybar_night_mode.bash)
  );
  waybar_sound = (
    patchScriptBin "waybar_custom_sound" (
      builtins.readFile ./files/waybar_scripts/waybar_sound_linux.bash
    )
  );
  waybar_temperature = (
    patchScriptBin "waybar_custom_temperature" (
      builtins.readFile ./files/waybar_scripts/waybar_temperature_linux.bash
    )
  );
in
{
  imports = [ ];

  options.me = {
    waybar.enable = lib.mkOption {
      type = lib.types.bool;
      default = false;
      example = true;
      description = "Whether we want to install waybar.";
    };

    waybar.config = lib.mkOption rec {
      apply = lib.recursiveUpdate default;
      inherit (settings_format) type;
      default = {
        # "height": 10, # Waybar height (to be removed for auto height)
        "modules-left" = [
          "sway/workspaces"
          "sway/mode"
        ];
        "modules-center" = [ "sway/window" ];
        "modules-right" = [
          "custom/night_mode"
          "custom/temperature"
          "custom/sound"
          "custom/available_memory"
          "custom/battery"
          "idle_inhibitor"
          "custom/clock"
          "tray"
        ];
        "sway/workspaces" = {
          "disable-scroll" = true;
        };
        "sway/mode" = {
          "format" = "<span style=\"italic\">{}</span>";
        };
        "sway/window" = {
          "format" = "{title}";
        };
        "idle_inhibitor" = {
          "format" = "{icon}";
          "format-icons" = {
            "activated" = "☕"; # ☕
            "deactivated" = "💤"; # ☾☁⛾⛔⏾⌛⏳💤
          };
        };
        "tray" = {
          # "icon-size" = 21;
          "spacing" = 10;
        };
        "custom/clock" = {
          "exec" = "waybar_custom_clock";
          "return-type" = "json";
          "restart-interval" = 30;
        };
        "custom/battery" = {
          "exec" = "waybar_custom_battery";
          "return-type" = "json";
          "restart-interval" = 30;
        };
        "custom/available_memory" = {
          "exec" = "waybar_custom_available_memory";
          "return-type" = "json";
          "restart-interval" = 30;
        };
        "custom/sound" = {
          "exec" = "waybar_custom_sound";
          "return-type" = "json";
          "restart-interval" = 30;
        };
        "custom/temperature" = {
          "exec" = "waybar_custom_temperature";
          "return-type" = "json";
          "restart-interval" = 30;
        };
        "custom/night_mode" = {
          "exec" = "waybar_night_mode";
          "return-type" = "json";
          "restart-interval" = 30;
          "on-click" = "pkill -USR1 -f waybar_night_mode";
        };
      };
      example = null;
      description = "Waybar's config in nix form.";
    };
  };

  config = lib.mkIf (config.me.waybar.enable && config.me.graphical) {
    environment.systemPackages = with pkgs; [
      waybar
    ];

    me.swayIncludes = [
      waybar_sway_config
    ];

    services.upower.enable = true; # for battery

    nixpkgs.overlays = [
      (final: prev: {
        waybar = pkgs.symlinkJoin {
          name = prev.waybar.name;
          paths = [ prev.waybar ];
          nativeBuildInputs = [ pkgs.makeWrapper ];
          postBuild = ''
            wrapProgram $out/bin/waybar --prefix PATH : ${
              lib.makeBinPath [
                waybar_available_memory
                waybar_battery
                waybar_clock
                waybar_night_mode
                waybar_sound
                waybar_temperature
                final.python3 # for clock TODO python should not be in the system packages, maybe switch to a venv? ref https://nixos.wiki/wiki/Python
                final.bc # for temperature and sound
                final.jq # for memory, battery, sound, night mode, and temperature
                final.upower # for battery
                final.wlsunset # for night mode
              ]
            }
          '';
        };
      })
    ];
  };
}
