{ pkgs, hyper, rice, ... }:
let
  sep = " ";
in {
  sops.secrets = {
    "nx2site/radicale/password" = { };
  };
  home.packages = with pkgs; [
    (writeShellApplication { name = "waybar_mode"; text = /*bash*/ ''
      print_help() {
          echo "Usage: waybar_mode {set <string>|unset}"
      }
      if [ $# -lt 1 ]; then
          print_help; exit 1;
      fi
      case "$1" in
          set)
              # Check if there is a second argument for the 'set' operation
              if [ $# -eq 2 ]; then
                echo "$2" > /tmp/waybar-mode
                pkill -RTMIN+8 waybar
              else
                  echo "Error: 'set' operation requires exactly one string argument."
                  print_help
                  exit 1
              fi
              ;;
          unset)
              echo "" > /tmp/waybar-mode
              pkill -RTMIN+8 waybar
              ;;
          *)
              echo "Error: Unknown command '$1'"
              print_help
              exit 1
              ;;
      esac
      exit 0
    '';})
    (writeShellApplication { name = "cclock"; text = /*bash*/ ''
      ord=$(date +"%e" | awk '{printf("%d%s\n", $1, ($1==11||$1==12||$1==13)?"th":((($1%10)==1)?"st":((($1%10)==2)?"nd":((($1%10)==3)?"rd":"th"))))}')
      if [ $# -eq 0 ]; then
        echo "󰃮${sep}$(date +'%A the')" "$ord" "of" "$(date +'%B')" " ${sep}$(date +'%R')"
      elif [ "$1" = "--no-icons" ]; then
        echo "$(date +'%A the')" "$ord" "of" "$(date +'%B')"  "$(date +'%R')"
      fi
    '';})
    (writers.writePython3Bin "caldav_event" {
      libraries = with pkgs.python3Packages; [ caldav ics pytz ];
      flakeIgnore = [ "E302" "E305""E501" "E261" ];
    } /* python */ ''
import os
import json
from caldav import DAVClient
from datetime import datetime, timezone
from ics import Calendar
from pytz import UTC

def get_password(password_file):
    with open(password_file, "r") as file:
        return file.read().strip()

def datetime_converter(obj):
    if isinstance(obj, datetime):
        return obj.isoformat()
    return obj

def datetime_parser(dct):
    for key, value in dct.items():
        if isinstance(value, str):
            try:
                dct[key] = datetime.fromisoformat(value)
            except ValueError:
                pass
    return dct

def load_cache(cache_file):
    if os.path.exists(cache_file):
        with open(cache_file, "r") as file:
            return json.load(file, object_hook=datetime_parser)
    return None

def save_cache(cache_file, data):
    with open(cache_file, "w") as file:
        json.dump(data, file, default=datetime_converter)


def get_ongoing_or_next_event(url, username, password):
    now = datetime.now(timezone.utc)

    try:
        client = DAVClient(url, username=username, password=password)
        principal = client.principal()
        calendars = principal.calendars()

        next_event_dict = {
            'event_name': "fake",
            'event_begin': datetime(9000, 1, 1, tzinfo=UTC), # in the year 9000
            'event_end': datetime(9000, 1, 1, 8, tzinfo=UTC),
        }

        for calendar in calendars:
            for event in calendar.events():
                calendar_parsed = Calendar(event.data)
                for ics_event in calendar_parsed.events:
                    event_dict = {}
                    event_dict['event_name'] = ics_event.name or "(No Title)"
                    event_dict['event_begin'] = ics_event.begin.astimezone(timezone.utc)
                    event_dict['event_end'] = ics_event.end.astimezone(timezone.utc)

                    if event_dict['event_begin'] <= now and now <= event_dict['event_end']:
                        return event_dict
                    elif event_dict['event_begin'] >= now and next_event_dict['event_begin'] > event_dict['event_begin']:
                        next_event_dict = event_dict
        return next_event_dict

    except Exception as e:
        print(f"Error accessing {url}: {e}")
        return None

if __name__ == "__main__":
    password_file = "/home/nx2/.config/sops-nix/secrets/nx2site/radicale/password"  # Path to password file
    cache_file = "/tmp/caldav_event_cache.json"  # Path to cache file
    url = "https://dav.${hyper.domain}/"
    username = "${hyper.user}"
    password = get_password(password_file)

    event_dict = load_cache(cache_file)
    now = datetime.now(timezone.utc).timestamp()

    if event_dict is None or event_dict['event_begin'].timestamp() <= now and now < event_dict['event_end'].timestamp():
        event_dict = get_ongoing_or_next_event(url, username, password)
        if event_dict is None:
            print("No upcoming events found.")
            exit(0)
        cache_data = {
            "event_name": event_dict['event_name'] if event_dict is not None else None,
            "event_begin": event_dict['event_begin'] if event_dict is not None else None,
            "event_end": event_dict['event_end'] if event_dict is not None else None
        }
        save_cache(cache_file, cache_data)

        if event_dict:
            event_start = event_dict['event_begin'].timestamp()
            event_end = event_dict['event_end'].timestamp()

            if event_start <= now <= event_end:
                time_remaining = event_end - now
                hours, rem = divmod(int(time_remaining), 3600)
                minutes, _ = divmod(rem, 60)
                print(f"{event_dict['event_name']} ends in {hours} hour{'s ' if hours != 1 else ' '}and {minutes} minute{'s ' if minutes != 1 else ' '}")
            else:
                time_until_start = event_start - now
                hours, rem = divmod(int(time_until_start), 3600)
                minutes, _ = divmod(rem, 60)
                print(f"{event_dict['event_name']} starts in {hours} hour{'s ' if hours != 1 else ' '}and {minutes} minute{'s ' if minutes != 1 else ' '}")
        else:
            print("No upcoming events found.")
'')
  ];

  programs.waybar = {
    enable = true;
    package = pkgs.waybar;
    settings = {
      bar = {
        # height = 20;
        layer = "top";
        position = "bottom";
        margin-top = 0;
        # margin-left = rice.gap-size;
        # margin-bottom = rice.gap-size;
        # margin-right = rice.gap-size;
        margin-left = 0;
        margin-bottom = 0;
        margin-right = 0;
        spacing = 10;
        fixed-center = true;
        modules-left = [
          # "cpu"
          # "memory"
          "wireplumber"
          "backlight"
          "battery"
          "network"
          "hyprland/window"
        ];
        modules-center = [
          "hyprland/workspaces"
        ];
        modules-right = [
          "custom/mode"
          # "custom/caldav_event"
          "custom/cclock"
          "tray"
        ];
        "hyprland/workspaces" = {
          on-click = "activate";
          format = "{name}";
          all-outputs = false;
          active-only = false;
        };
        "hyprland/window" = {
          # format = "${sep}{}";
          format = "{}";
          separate-outputs = true;
        };
        "custom/cclock" = {
          exec = "cclock";
          restart-interval = 60;
        };
        "custom/caldav_event" = {
          format = "󰃰${sep}{}";
          exec = "caldav_event";
          restart-interval = 60;
          max-width = 60;
        };
        "custom/mode" = {
          exec = "cat /tmp/waybar-mode";
          interval = "once";
          signal = 8;
        };

        cpu = {
          interval = 1;
          format = "󰍛${sep}{}%";
          max-length = 10;
        };
        memory = {
          interval = 5;
          format = "${sep}{avail:.0f}G free";
        };
        battery = {
          interval = 60;
          tooltip = false;
          format = "{icon}${sep}{capacity}%";
          states = {
            warning = 15;
            critical = 5;
          };
          format-icons = [
            " "
            " "
            " "
            " "
            " "
          ];
          format-charging = "{icon}${sep}+{capacity}%";
          format-plugged = "{icon}${sep}P{capacity}%";
          format-full = "{icon}${sep}F{capacity}%";
        };
        backlight = {
          device = "eDP-1";
          format = "{icon}${sep}{percent}%";
          format-icons = [
            ""
            ""
            ""
            ""
            ""
            ""
            ""
            ""
            ""
          ];
        };
        network = {
          format-wifi = "${sep}{essid}";
          format-ethernet = "󰈀${sep}Wired";
          format-disconnected = "󰌙${sep}Disconnected";
        };
        wireplumber = {
          format = "󰕾${sep}{volume}%";
          format-muted = "󰝟${sep}--%";
        };
      };
    };
    style = with rice.color; let f = rice.lib.hex-to-rgb-comma-string; in ''
      * {
        font-family: ${rice.font.code.name};
        font-size: 1em;
        min-height: 0px;
        margin: 0px;
        padding: 0px;
      }

      window#waybar {
        background-color: rgba(${f background},${builtins.toString rice.transparency});
        transition-duration: 5s;
        transition-property: background-color;
        /* border: ${builtins.toString rice.border-width}px solid rgb(${f border}); */
        /* margin: ${builtins.toString rice.gap-size}px; */
        /* border-radius: ${builtins.toString rice.rounding}px; */
      }

      #clock,
      #custom-cclock,
      #custom-mode,
      #custom-caldav-event,
      #battery,
      #cpu,
      #tray,
      #disk,
      #backlight,
      #network,
      #wireplumber,
      #memory,
      #window,
      #workspaces {
        padding: 0px 3px;
        margin-top: 0.3em;
        border-radius: ${builtins.toString rice.rounding}px;
        color: rgb(${f accent.bright});
      }

      #workspaces {
        font-family: ${rice.font.code.name};
      }

      #workspaces button {
        color: rgb(${f accent.base});
        padding-left: 15px;
        padding-right: 15px;
        border-radius: ${builtins.toString rice.rounding}px;
      }

      #workspaces button.active {
        color: rgb(${f background});
        background-color: rgb(${f accent.base});
      }

      #workspaces button:hover {
        color: rgb(${f tertiary.bright});
      }

      #workspaces button.urgent {
        background-color: rgba(${f magenta.base},${builtins.toString rice.transparency});
      }

      #custom-mode {
        color: rgb(${f red.base});
      }

      #window, #custom-caldav_event {
        font-family: ${rice.font.base.name}, ${rice.font.code.name};
        color: rgb(${f tertiary.bright});
      }

      #wireplumber.muted {
        color: rgb(${f tertiary.bright});
      }
      #wireplumber {
        padding-left: 10px;
      }

      #battery.warning:not(.charging) {
        color: rgb(${f green.base});;
      }

      #battery.charging {
        color: rgb(${f green.base});
      }

      #battery.critical {
        background: rgb(${f negative.base});
        color: rgb(${f foreground});
      }
    '';

      #battery.critical:not(.charging) {
  };
}
