---
- name: Copy workstation host Linux dotfiles
  tags: [dotfiles, dotfiles:workstation, gnome]
  ansible.builtin.copy:
    src: "{{ playbook_dir }}/../dotfiles/workstation_host_linux/{{ item.src }}"
    dest: "{{ user_home }}/{{ item.dest }}"
    owner: "{{ username }}"
    group: "{{ user_group }}"
    mode: "{{ item.mode }}"
  loop: "{{ workstation_host_linux_dotfiles | default([]) }}"
  loop_control:
    label: "{{ item.dest }}"

- name: Ensure GNOME extension directories exist
  tags: [packages, gnome]
  ansible.builtin.file:
    path: "{{ item }}"
    state: directory
    owner: "{{ username }}"
    group: "{{ user_group }}"
    mode: "0755"
  loop:
    - "{{ user_home }}/.cache/gnome-shell/extensions"
    - "{{ user_home }}/.local/share/gnome-shell/extensions"

- name: Gather workstation user account data
  tags: [packages, gnome]
  ansible.builtin.getent:
    database: passwd
    key: "{{ username }}"

- name: Set workstation GNOME session environment
  tags: [packages, gnome]
  ansible.builtin.set_fact:
    workstation_user_uid: "{{ ansible_facts.getent_passwd[username][1] }}"
    workstation_gnome_extension_dir: "{{ user_home }}/.cache/gnome-shell/extensions"
    workstation_gnome_environment:
      HOME: "{{ user_home }}"
      XDG_RUNTIME_DIR: "/run/user/{{ ansible_facts.getent_passwd[username][1] }}"
      DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ ansible_facts.getent_passwd[username][1] }}/bus"

- name: Read current workstation GNOME managed settings
  tags: [gnome]
  ansible.builtin.command:
    argv:
      - gsettings
      - get
      - "{{ item.schema }}{{ ':' ~ item.path if item.path is defined else '' }}"
      - "{{ item.key }}"
  become_user: "{{ username }}"
  environment: "{{ workstation_gnome_environment }}"
  loop: "{{ workstation_gnome_managed_settings | default([]) }}"
  loop_control:
    label: >-
      {{ item.schema }}{{ ':' ~ item.path if item.path is defined else '' }} {{ item.key }}
  register: workstation_gnome_managed_settings_current
  changed_when: false

- name: Apply workstation GNOME managed settings
  tags: [gnome]
  ansible.builtin.command:
    argv:
      - gsettings
      - set
      - "{{ item.item.schema }}{{ ':' ~ item.item.path if item.item.path is defined else '' }}"
      - "{{ item.item.key }}"
      - "{{ item.item.value }}"
  become_user: "{{ username }}"
  environment: "{{ workstation_gnome_environment }}"
  loop: "{{ workstation_gnome_managed_settings_current.results | default([]) }}"
  loop_control:
    label: >-
      {{ item.item.schema }}{{ ':' ~ item.item.path if item.item.path is defined else '' }} {{ item.item.key }}
  changed_when: true
  when: item.stdout | trim != item.item.value

- name: Apply workstation GNOME extension dconf settings
  tags: [gnome]
  ansible.builtin.command:
    argv:
      - dconf
      - write
      - "{{ item.path }}{{ item.key }}"
      - "{{ item.value }}"
  become_user: "{{ username }}"
  loop: "{{ workstation_gnome_extension_dconf_settings | default([]) }}"
  loop_control:
    label: "{{ item.path }}{{ item.key }}"
  changed_when: true

- name: Check whether VS Code CLI is available on workstation host
  tags: [packages, vscode]
  ansible.builtin.command:
    argv:
      - code
      - --version
  become_user: "{{ username }}"
  environment:
    HOME: "{{ user_home }}"
  register: workstation_vscode_cli
  changed_when: false
  failed_when: false
  when: (workstation_host_vscode_extensions | default([])) | length > 0

- name: Ensure VS Code CLI is available before managing extensions
  tags: [packages, vscode]
  ansible.builtin.fail:
    msg: Ensure Visual Studio Code is installed before managing workstation VS Code extensions.
  when:
    - (workstation_host_vscode_extensions | default([])) | length > 0
    - workstation_vscode_cli.rc != 0

- name: Read installed VS Code extensions on workstation host
  tags: [packages, vscode]
  ansible.builtin.command:
    argv:
      - code
      - --list-extensions
  become_user: "{{ username }}"
  environment:
    HOME: "{{ user_home }}"
  register: workstation_vscode_extensions_current
  changed_when: false
  when:
    - (workstation_host_vscode_extensions | default([])) | length > 0
    - workstation_vscode_cli.rc == 0

- name: Install VS Code extensions on workstation host
  tags: [packages, vscode]
  ansible.builtin.command:
    argv:
      - code
      - --install-extension
      - "{{ item }}"
      - --force
  become_user: "{{ username }}"
  environment:
    HOME: "{{ user_home }}"
  loop: "{{ workstation_host_vscode_extensions | default([]) }}"
  loop_control:
    label: "{{ item }}"
  when:
    - workstation_vscode_cli.rc == 0
    - item not in (workstation_vscode_extensions_current.stdout_lines | default([]))

- name: Download workstation GNOME extension archives
  tags: [packages, gnome]
  ansible.builtin.get_url:
    url: >-
      https://extensions.gnome.org/download-extension/{{ item.uuid }}.shell-extension.zip?version_tag={{ item.version_tag }}
    dest: "{{ workstation_gnome_extension_dir }}/{{ item.uuid }}.zip"
    owner: "{{ username }}"
    group: "{{ user_group }}"
    mode: "0644"
  loop: "{{ workstation_gnome_extensions | default([]) }}"
  loop_control:
    label: "{{ item.uuid }}"

- name: Check installed workstation GNOME extensions
  tags: [packages, gnome]
  ansible.builtin.stat:
    path: "{{ user_home }}/.local/share/gnome-shell/extensions/{{ item.uuid }}/metadata.json"
  loop: "{{ workstation_gnome_extensions | default([]) }}"
  loop_control:
    label: "{{ item.uuid }}"
  register: workstation_gnome_extension_install_state

- name: Install workstation GNOME extensions from downloaded archives
  tags: [packages, gnome]
  ansible.builtin.command:
    cmd: "gnome-extensions install --force {{ workstation_gnome_extension_dir }}/{{ item.uuid }}.zip"
  become_user: "{{ username }}"
  environment: "{{ workstation_gnome_environment }}"
  loop: "{{ workstation_gnome_extensions | default([]) }}"
  loop_control:
    label: "{{ item.uuid }}"
  when: >-
    not (
      workstation_gnome_extension_install_state.results
      | selectattr('item.uuid', 'equalto', item.uuid)
      | map(attribute='stat.exists')
      | first
      | default(false)
    )

- name: Read current workstation GNOME enabled extensions
  tags: [gnome]
  ansible.builtin.command:
    cmd: gsettings get org.gnome.shell enabled-extensions
  become_user: "{{ username }}"
  environment: "{{ workstation_gnome_environment }}"
  register: workstation_enabled_gnome_extensions_current
  changed_when: false

- name: Compute desired workstation GNOME enabled extensions
  tags: [gnome]
  ansible.builtin.set_fact:
    workstation_enabled_gnome_extensions_current_list: >-
      {{
        (
          workstation_enabled_gnome_extensions_current.stdout
          | default('')
          | regex_search('\[.*\]')
          | default('[]', true)
        )
        | from_yaml
      }}

- name: Build desired workstation GNOME enabled extensions list
  tags: [gnome]
  ansible.builtin.set_fact:
    workstation_enabled_gnome_extensions_desired: >-
      {{
        (
          workstation_enabled_gnome_extensions_current_list
          + (
            workstation_gnome_extensions
            | default([])
            | selectattr('enabled', 'defined')
            | selectattr('enabled')
            | map(attribute='uuid')
            | list
          )
        )
        | difference(workstation_disabled_gnome_extensions | default([]))
        | unique
        | sort
      }}

- name: Build workstation GNOME extensions gsettings payload
  tags: [gnome]
  ansible.builtin.set_fact:
    workstation_enabled_gnome_extensions_desired_gsettings: >-
      [{% for extension_uuid in workstation_enabled_gnome_extensions_desired -%}
      '{{ extension_uuid | replace("'", "\\'") }}'{% if not loop.last %}, {% endif %}
      {%- endfor %}]

- name: Determine whether workstation GNOME enabled extensions must change
  tags: [gnome]
  ansible.builtin.set_fact:
    workstation_gnome_extensions_state_changed: >-
      {{ (workstation_enabled_gnome_extensions_current_list | sort) != workstation_enabled_gnome_extensions_desired }}

- name: Apply workstation GNOME enabled extensions list
  tags: [gnome]
  ansible.builtin.command:
    argv:
      - gsettings
      - set
      - org.gnome.shell
      - enabled-extensions
      - "{{ workstation_enabled_gnome_extensions_desired_gsettings }}"
  become_user: "{{ username }}"
  environment: "{{ workstation_gnome_environment }}"
  changed_when: workstation_gnome_extensions_state_changed
  when: workstation_gnome_extensions_state_changed

- name: Enable UFW firewall on workstation
  tags: [services, packages]
  community.general.ufw:
    state: enabled
  when: workstation_firewall_backend | default('ufw') == 'ufw'
