- tags:
    - wireguard
  become: yes
  when: wireguard__state == 'present'
  vars:
    wg_net: "{{ hostvars[inventory_hostname][wireguard__name] }}"
    wg_host: "{{ wg_net.hosts[inventory_hostname] }}"
    all_peers: "{{ wg_host.peers is defined and wg_host.peers == 'all' }}"
    netdev_path: "/etc/systemd/network/60-{{ wg_net.if }}.netdev"
    network_path: "/etc/systemd/network/61-{{ wg_net.if }}.network"
  block:
    - debug: var=wg_net
    - debug: var=wg_host
    - debug: var=all_peers

    - name: Install packages
      tags:
        - never
        - packages
      apt:
        name:
          - wireguard
        install_recommends: no

    - name: systemctl enable systemd-networkd
      systemd:
        name: systemd-networkd
        enabled: yes
        state: started

    - name: mkdir /etc/wireguard
      file:
        path: /etc/wireguard
        state: directory

    - name: "wg genkey /etc/wireguard/private-{{ wg_net.if }}.key"
      tags: wireguard-config
      shell: wg genkey | tee /etc/wireguard/private-{{ wg_net.if }}.key | wg pubkey > /etc/wireguard/public-{{ wg_net.if }}.key
      args:
        creates: /etc/wireguard/private-{{ wg_net.if }}.key
      register: wg_private_key_gen

    - when: wg_private_key_gen.changed
      tags: wireguard-config
      fetch:
        src: "/etc/wireguard/public-{{ wg_net.if }}.key"
        dest: "files"

    - tags: wireguard-config
      slurp:
        src: "/etc/wireguard/private-{{ wg_net.if }}.key"
      register: wg_private_key

    - name: "Make {{ netdev_path }}"
      notify: systemctl restart systemd-networkd
      tags: wireguard-config

      copy:
        dest: "{{ netdev_path }}"
        content: |
          [NetDev]
          Name={{ wg_net.if }}
          Kind=wireguard
          Description=Wireguard VPN

          [WireGuard]
          PrivateKey={{ wg_private_key['content'] | b64decode }}
          {% if wg_host.listen_port is defined %}
          ListenPort={{ wg_host.listen_port }}
          {% endif %}
          {% for hostname in wg_net.hosts|sort %}
          {% set host = wg_net.hosts[hostname] %}
          {% set present = not (host.state is defined) or host.state == 'present' %}
          {% if present and (all_peers or host.endpoint is defined) and (hostname != inventory_hostname) %}

          # {{ hostname }}
          [WireGuardPeer]
          PublicKey={{ host.public_key if host.public_key is defined else lookup('file', hostname + '/etc/wireguard/public-{{ wg_net.if }}.key') }}
          {% if host.allowed_ips is defined %}
          {% for h in host.allowed_ips %}
          AllowedIPs={{ h }}
          {% endfor %}
          {% endif %}
          {% if host.ipv4 is defined %}
          AllowedIPs={{ host.ipv4 }}
          {% endif %}
          {% if host.ipv6 is defined %}
          AllowedIPs={{ host.ipv6 }}
          {% endif %}
          {% if host.endpoint is defined %}
          Endpoint={{ host.endpoint }}:{{ host.listen_port }}
          {% endif %}
          PersistentKeepalive=60
          {% endif %}
          {% endfor %}

    - name: "Make {{ network_path }}"
      tags: wireguard-config
      notify: systemctl restart systemd-networkd
      copy:
        dest: "{{ network_path }}"
        content: |
          [Match]
          Name={{ wg_net.if }}

          [Network]
          {% if wg_net.hosts[inventory_hostname].ipv4 is defined %}
          Address={{ wg_net.hosts[inventory_hostname].ipv4 }}/{{ wg_net.ipv4_prefix }}
          {% endif %}
          {% if wg_net.hosts[inventory_hostname].ipv6 is defined %}
          Address={{ wg_net.hosts[inventory_hostname].ipv6 }}/{{ wg_net.ipv6_prefix }}
          {% endif %}
          {% if wg_net.shared_routes is defined %}

          {% for route in wg_net.shared_routes %}
          [Route]
          Gateway={{ route.gateway }}
          Destination={{ route.net }}/{{ route.prefix }}
          {% endfor %}
          {% endif %}

- tags:
    - wireguard
  become: yes
  when: wireguard__state == 'absent'
  vars:
    wg_net: "{{ hostvars[inventory_hostname][wireguard__name] }}"
    netdev_path: "/etc/systemd/network/60-{{ wg_net.if }}.netdev"
    network_path: "/etc/systemd/network/61-{{ wg_net.if }}.network"
  block:
    - name: Remove old files
      file:
        path: "{{ item }}"
        state: absent
      notify: systemctl restart systemd-networkd
      with_items:
        - /etc/wireguard/private-{{ wg_net.if }}.key
        - /etc/wireguard/public-{{ wg_net.if }}.key
        - "{{ netdev_path }}"
        - "{{ network_path }}"

    - name: Checking for interface
      shell: "ip -j link show"
      changed_when: False
      register: ip_link

    - name: Removing interface
      shell: "ip -j link delete {{ wg_net.if }}"
      when: links[wg_net.if] is defined
      vars:
        links: "{{ ip_link.stdout | from_json | items2dict(key_name='ifname', value_name='ifname') }}"