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

with utils;
with lib;

let
  cfg = virtualisation.libvirtd;

  textfile = with types; coercedTo str (pkgs.writeText "spec.xml") path;

  domain = {
    options = {
      xml = mkOption {
        type = 
      };

      autostart = mkOption {
        type = types.bool;
        default = true;
      };
    };
  };

  define = let
    python = pkgs.python27.withPackages (ps: with ps; [ libvirt ]);
  in dCfg: ''
    #!${python}/bin/python

    import libvirt
    import sys

    conn = libvirt.open(None);
    if conn == None:
      print('Failed to open connection to hypervisor', file=sys.stderr)
      sys.exit(1)

    xmlFile = open(${escapeShellArg dCfg.xml}, 'r')
    dom = conn.defineXML(xmlFile.read(), 0)
    xmlFile.close()
    if dom == None:
      print('Failed to define domain', file=sys.stderr)
      sys.exit(1)

    dom.setAutostart(${if dCfg.autostart then "1" else "0"})

    conn.close()
    sys.exit(0)
  '';
in {
  options = {
    virtualisation.libvirtd = {
      domains = mkOption {
        type = with types; attrsOf (submodule guest);
        default = {};
      };
    };
  };

  config = mkIf (cfg.domains != {}) {
    systemd.services."libvirtd-guest@" = {
      after = [ "libvirtd.service" ];
      bindsTo = [ "libvirtd.service" ];

      before = [ "libvirt-guests.service" ];

      serviceConfig = {
        Type = "oneshot";
        RemainAfterExit = true;
      };

      path = with pkgs; [ libvirtd ];
    };

    systemd.services = mapAttrs' (dName: dCfg: nameValuePair ("libvirtd-guest@" + escapeSystemdPath dName + ".service") {
      serviceConfig = {
        ExecStart = pkgs.writeScript (dName + ".py") (define dCfg);
      };
    }) cfg.domains;

    systemd.services."libvirt-guests.service" = {
      wants = mapAttrsToList (dName: dCfg: "libvirtd-guest@" + escapeSystemdPath dName + ".service") cfg.domains;
    };
  };
}