#
# Use Waybar with our GUI.
#
# vim: et:ts=2:sw=2:
{
  lib,
  pkgs,
  config,
  ...
}:
let
  hostname = config.networking.hostName;
  isSmallScreen = (hostname == "utol");
in
{

  # Pull in some dependencies for our bar.
  environment.systemPackages = with pkgs; [ networkmanagerapplet ];

  # Enable the yubikey touch detector, for our icon.
  programs.yubikey-touch-detector.enable = true;

  #
  # Set up our waybar configuration in home-manager.
  #
  home-manager.users.deprekated =
    { pkgs, config, ... }:
    let

      icons = rec {
        calendar = "󰃭 ";
        clock = " ";
        puclock = "󱑆";
        cpu = "";
        ram = "";
        battery.charging = "󱐋";
        battery.horizontal = [
          " "
          " "
          " "
          " "
          " "
        ];
        battery.vertical = [
          "󰁺"
          "󰁻"
          "󰁼"
          "󰁽"
          "󰁾"
          "󰁿"
          "󰂀"
          "󰂁"
          "󰂂"
          "󰁹"
        ];
        battery.levels = battery.vertical;
        network.disconnected = "󰤮 ";
        network.ethernet = "󰈀 ";
        network.strength = [
          "󰤟 "
          "󰤢 "
          "󰤥 "
          "󰤨 "
        ];
        bluetooth.on = "󰂯";
        bluetooth.off = "󰂲";
        bluetooth.battery = "󰥉";
        volume.source = "󱄠";
        volume.muted = "󰝟";
        volume.levels = [
          "󰕿"
          "󰖀"
          "󰕾"
        ];
        idle = {
          on = "<span color='#${colors.red}'>󰅶</span>";
          off = "󰾪";
        };
        vpn = "󰌆 ";
        music = {
          playing = "";
          paused = "";
          stopped = "";
          missing = "󰌙";
        };

        speed = {
          slow = "󰾆";
          medium = "󰾅";
          fast = "󰓅";
        };
      };
      colors = config.lib.stylix.colors;

      # From the Waybar wiki.
      waybar-events = pkgs.writeScriptBin "waybar-events" ''
        #!${pkgs.python3}/bin/python3

        import calendar
        import subprocess
        import datetime
        import json
        import html
        import sys

        data = {}

        today = datetime.date.today().strftime("%Y-%m-%d")
        next_week = (datetime.date.today() +
                     datetime.timedelta(days=10)).strftime("%Y-%m-%d")
        tomorrow = (datetime.date.today() +
                     datetime.timedelta(days=1)).strftime("%Y-%m-%d")

        human_events = subprocess.check_output('khal list now ' + next_week, shell=True).decode('utf-8')
        machine_events = subprocess.check_output('khal list now ' + next_week + ' -d "Holidays in United States" --once -f "{title}|{start-date}|{start-time}" -df ""', shell=True).decode('utf-8')

        if not machine_events:
            sys.exit(0)

        next_event = machine_events.split("\n")[0]
        event, date, time = next_event.split('|')

        # Generate our hover-over text.
        lines = human_events.split("\n")
        new_lines = []
        for line in lines:
            if line.startswith("To hide observances") or (line == ""):
                continue

            clean_line = html.escape(line).split(" ::")[0]
            if len(clean_line) and not clean_line[0] in ['0', '1', '2']:
                clean_line = "\n<b><span color='#${colors.blue}'>"+clean_line+"</span></b>" if (',' in clean_line) else clean_line

            new_lines.append(clean_line)
        tooltip = "\n".join(new_lines).strip()

        if tomorrow in date:
          date = "tomorrow"
        else:
          weekday = datetime.datetime.fromisoformat(date).weekday()
          date = calendar.day_name[weekday].lower()


        # Add time suffixes when appropriate.
        time_suffix = ""
        if time:
          time_suffix = " @ " + time

        date_suffix = ""
        if today not in date:
          date_suffix = ", " + date


        # In the typical case, display the next event.
          data['text'] = html.escape(" " + event[0:30] + date_suffix + time_suffix)

        # Display our nice, human-readable event ouptut on hover.
        data['tooltip'] = tooltip

        # Finally, send the data to Waybar.
        print(json.dumps(data))
      '';

      waybar-title = pkgs.writeScriptBin "waybar-title" ''
        				#!${pkgs.bash}/bin/bash
                niri msg --json focused-window | jq -c '{text: (if ((.title | length) > 40) then (.title[:38] + "…") else .title end), tooltip: .app_id}' | sed 's/&[ $]/\&amp; /g'
      '';

      waybar-puck-countdown = pkgs.writeScriptBin "waybar-puck-countdown" ''
        #!${pkgs.python3}/bin/python3

        import json

        from datetime import datetime, timezone

        now       = datetime.now(timezone.utc)
        puck_day  = "2024-12-11 13:30:00-07:00"
        puck_time = datetime.fromisoformat(puck_day)
        until     = puck_time - now

        response = {
            "text": f" 󰧒 {until.days}d {until.seconds // 60 // 60}h",
            "tooltip": f"days until {puck_day}"
        }

        print(json.dumps(response))
      '';

    in
    {
      #
      # Core Waybar settings.
      #
      programs.waybar = {
        enable = true;
        systemd.enable = true;

        # Replace the package with a patched one.
        package = pkgs.waybar.overrideAttrs (prev: {
					patches = prev.patches ++ [ ./01-fix-privacy-null-pointer-deref.patch ];
        });
      };

      programs.waybar.settings.mainBar = {
        layer = "top";
        #mode = "overlay";

        modules-left = [
          "clock"
          "clock#otherzone"
          "mpd"
        ];
        modules-center = [
          "custom/title"
          "wlr/taskbar"
        ];
        modules-right = [
          "tray"
          "custom/events"
          "privacy"
          "custom/yubikey"
          "wireplumber"
          "custom/puckdown"
          "battery"
        ];

        battery = {
          interval = 5;
          format = "{icon} {capacity}%";
          format-charging = "{icon} {capacity}% ${icons.battery.charging}";
          format-icons = icons.battery.levels;
          states.warning = 30;
          states.critical = 15;
        };

        cpu = {
          format = "${icons.cpu} {usage}% @ {avg_frequency:0.1f}GHz";
        };

        memory = {
          format = "${icons.ram}  {used:0.1f}G / {total:0.1f}G";
        };

        clock = {
          interval = 1;
          format = "${icons.clock} {:%H:%M %A, %B %d %Z}";

          tooltip-format = "<tt>${icons.calendar}<u><b> {:%a, %Y-%m-%d}</b></u>\n\n{calendar}</tt>";

          calendar = {
            mode = "month";
            format = {
              weeks = "<b>W{}</b>";
              months = "<span color='#${colors.magenta}'><b>{}</b></span>";
              days = "<span color='#${colors.blue}'><b>{}</b></span>";
              weekdays = "<span color='#${colors.cyan}'><b>{}</b></span>";
              today = "<span color='#${colors.green}'><b>{}</b></span>";
            };
          };
        };

        "clock#otherzone" = {
          interval = 1;
          format = "${icons.puclock} {:%H:%M %Z}";
          timezone = "Europe/Amsterdam";
          tooltip-format = ''
            <b><u>Homosexuality Statistics</u></b>

            Homosexuality is <b><span color='#${colors.green}'>online</span></b>.
            Homosexuality levels are <b><span color='#${colors.red}'>CRITICAL</span></b>.
          '';
        };

        network = {
          on-click = "${pkgs.networkmanagerapplet}/bin/nm-connection-editor";
          tooltip = false;
          format-disconnected = icons.network.disconnected;
          format-ethernet = "${icons.network.ethernet}";
          format-wifi = "{icon} {essid}";
          format-icons = icons.network.strength;
        };

        bluetooth = {
          format = "{icon}";
          format-disabled = "{icon}";
          format-icons = {
            inherit (icons.bluetooth) on off;
            connected = icons.bluetooth.on;
          };
          format-connected = "{icon} {device_alias}";
        };
        "bluetooth#battery" = {
          format = "";
          format-connected-battery = "${icons.bluetooth.battery} {device_battery_percentage}%";
        };

        wireplumber = {
          on-click = "${pkgs.pavucontrol}/bin/pavucontrol -t 1";
          format = "{icon} {volume}%";
          tooltip-format = "${icons.volume.source}";
          format-muted = "${icons.volume.muted}";
          format-icons = icons.volume.levels;
          reverse-scrolling = 1;
        };

        # Displays an icon when our yubikey is waiting for touch.
        "custom/yubikey" = {
          exec = ./waybar-yubikey.sh;
          return-type = "json";
        };

        "custom/events" = {
          exec = "${waybar-events}/bin/waybar-events";
          format = "{}";
          tooltip = true;
          return-type = "json";
          interval = 60;
          on-click = "${pkgs.wezterm}/bin/wezterm start ikhal";
        };

        "custom/title" = {
          exec = "${waybar-title}/bin/waybar-title";
          format = "{}";
          tooltip = true;
          return-type = "json";
          interval = 1;
        };

        "custom/puckdown" = {
          exec = "${waybar-puck-countdown}/bin/waybar-puck-countdown";
          format = "{}";
          tooltip = true;
          return-type = "json";
          interval = 60 * 5;
        };

        "wlr/taskbar" = {
          format = "{icon}";
          tooltip-format = "{app_id}";

          on-click = "activate";
        };

        tray = {
          icon-size = 21;
          spacing = 10;
        };

        # Display indicators when we're sharing video or audio.
        privacy = {
          icon-spacing = 4;
          icon-size = 18;
          transition-duration = 250;
          modules = [
            {
              type = "screenshare";
              tooltip = false;
              tooltip-icon-size = 24;
            }
            {
              type = "audio-out";
              tooltip = false;
              tooltip-icon-size = 24;
            }
            {
              type = "audio-in";
              tooltip = false;
              tooltip-icon-size = 24;
            }
          ];
        };

        mpd = {
          on-click = "mpc toggle";
          format = "${icons.music.playing} {artist} - {title}";
          format-paused = "${icons.music.paused} {artist} - {title}";
          format-stopped = "";
          format-disconnected = "${icons.music.missing}";
          tooltip-format = "${icons.music.playing} {artist} - {title}";
          max-length = 60;
        };

        idle_inhibitor = {
          format = "{icon}";
          format-icons = {
            activated = icons.idle.on;
            deactivated = icons.idle.off;
          };

          tooltip-format-activated = "System <span color='#${colors.orange}'><b>blocked</b></span> from going idle.";
          tooltip-format-deactivated = "System <span color='#${colors.green}'><b>allowed</b></span> to go idle.";
        };
      };
      stylix.targets.waybar.enable = false;
      programs.waybar.style =
        let
          colors = config.lib.stylix.colors;
          modules = s: "${s ".modules-left"}, ${s ".modules-center"}, ${s ".modules-right"}";
          module = s: modules (m: "${m} > ${s} > *");
        in
        ''
          * {
              border: none;
              font-family: ${config.stylix.fonts.monospace.name};
              font-weight: 400;
              font-size: ${if isSmallScreen then "17" else toString config.stylix.fonts.sizes.desktop}px;
              color: #${colors.base06};
          }

          window#waybar {
              background: #${colors.base00};
          }

          #taskbar button {
            padding: 0 0.4em;
          }

          #taskbar button.active {
            background: #${colors.base01};
          }

          #tray image,
          #taskbar image {
             -gtk-icon-transform: scale(0.75);
             margin: -5px -4px;
             padding: 0px 2px;
          }

          ${modules lib.id} {
              margin: 0;
          }

          ${module "*"} {
            padding: 0 5px;
            margin: 0;
            font-size: 75%;
          }

          ${module ":not(:first-child)"} {
            border-left: 1px solid #${colors.base01};
          }

          ${module ":not(:last-child)"} {
            border-right: 1px solid #${colors.base01};
          }

          #battery.charging {
              color: #${colors.green};
          }

          #battery.warning:not(.charging) {
              color: #${colors.yellow};
          }

          #battery.critical:not(.charging) {
              animation: critical-blink steps(8) 1s infinite alternate;
          }

          @keyframes critical-blink {
              to {
                  color: #${colors.red};
              }
          }
        '';

      #
      # Restart waybar when niri starts.
      #
      programs.niri.settings.spawn-at-startup = [
        {
          command = [
            "systemctl"
            "--user"
            "restart"
            "waybar"
          ];
        }
        { command = [ "nm-applet" ]; }
      ];
    };
}
