{
  nixosConfig,
  lib,
  config,
  ...
}: {
  imports = [
    ./hooks
  ];

  services.taskwarrior-sync = {
    enable = true;
  };

  programs.taskwarrior = let
    projects = import ./projects {};

    mkContext = project:
      if builtins.hasAttr "subprojects" project
      then
        lib.lists.flatten (
          (builtins.map mkContext (builtins.map (mkProject project) project.subprojects))
          ++ (mkContext (builtins.removeAttrs project ["subprojects"]))
        )
      else [
        {
          inherit (project) name;
          value = let
            name =
              if builtins.hasAttr "pname" project
              then project.pname
              else project.name;
          in {
            read = "project:${name}";
            write = "project:${name}";
            rc = {
              neorg_path =
                if builtins.hasAttr "neorg_path" project
                then project.neorg_path
                else "${project.prefix}/${project.name}/index.norg";
            };
          };
        }
      ];
    mkProject = project: subproject: let
      pname =
        if builtins.hasAttr "pname" project
        then project.pname
        else project.name;
    in
      if builtins.isString subproject
      then {
        name = "${project.name}_${subproject}";
        pname = "${pname}.${subproject}";
        neorg_path =
          if builtins.hasAttr "neorg_path_prefix" project
          then "${project.neorg_path_prefix}/${subproject}/index.norg"
          else "${project.prefix}/${project.name}/${subproject}/index.norg";
      }
      else if builtins.isAttrs subproject
      then let
        name = builtins.elemAt (builtins.attrNames subproject) 0;
      in {
        name = "${project.name}_${name}";
        pname = "${pname}.${name}";
        prefix = "${project.prefix}/${project.name}";
        neorg_path_prefix = "${project.prefix}/${project.name}/${name}";
        subprojects = builtins.elemAt (builtins.attrValues subproject) 0;
      }
      else builtins.throw "Subproject not a string or a attrs: ${subproject}";

    context =
      builtins.listToAttrs (lib.lists.flatten (builtins.map mkContext projects));
  in {
    enable = true;
    colorTheme = ./nord.theme;
    extraConfig = ''
      # This include just contains my taskd user credentials
      include ${nixosConfig.age.secrets.taskserverCredentials.path}
    '';
    config = {
      news.version = "2.6.0";
      complete.all.tags = true;
      list.all = {
        projects = true;
        tags = true;
      };
      regex = true;
      weekstart = "Monday";
      uda = {
        total_active_time = {
          type = "duration";
          label = "Total active time";
        };
      };
      alias = {
        mod = "modify";
        n = "execute neorg --task";
        fstart = "execute neorg fstart";
      };
      color = true;

      hooks.location = "${config.xdg.configHome}/task/hooks";

      urgency.uda.priority = {
        H.coefficient = 6.0;
        M.coefficient = 0;
        L.coefficient = -1.8;
      };

      inherit context;

      taskd = {
        server = "taskserver.vhack.eu:53589";
        trust = "strict";
        ca =
          nixosConfig.age.secrets.taskserverCA.path;
        key =
          nixosConfig.age.secrets.taskserverPrivate.path;
        certificate =
          nixosConfig.age.secrets.taskserverPublic.path;
      };
    };
  };
}