---
# @action Ensures software is installed
# Installs software on RedHat based Systems from official repositories using `DNF`
- name: "Ensure {{ software_item }} is installed (dnf)"
  dnf:
    name: "{{ software_package[software_item]['dnf'] }}"
    state: present
  when: "'dnf' in available_methods"
  register: dnf_result
  failed_when: "dnf_result.rc == 1 and 'Failed to install' not in dnf_result.msg"

- name: "Ensure {{ software_item }} is installed (go)" # noqa 301 305
  shell: |
    {%- if software_package[software_item]['go'] | regex_search('go (?i)(install|build|get)') -%}
    {{ software_package[software_item]['go'] }}
    {%- else -%}
    go get {{ software_package[software_item]['go'] }}
    {%- endif -%}
  environment:
    GOPATH: "{{ '/home/' + ansible_user + '/.local/go' }}"
  register: go_result
  when:
    - "'go' in available_methods"
    - "(dnf_result.rc is defined and dnf_result.rc == 1 and 'Failed to install' in dnf_result.msg) or dnf_result.skipped is defined or \
        ((dnf_result.changed and dnf_result.failed) and (not dnf_result.changed))"
  failed_when: false

- name: "Ensure {{ software_item }} is installed (cargo)" # noqa 301 305
  shell: |
    {%- if 'cargo install' in "software_package[software_item]['cargo']" -%}
    {{ software_package[software_item]['cargo'] }}
    {%- else -%}
    cargo install {{ software_package[software_item]['cargo'] }}
    {%- endif -%}
  args:
    executable: /bin/bash
  register: cargo_result
  when:
    - "'cargo' in available_methods"
    - "(dnf_result.rc is defined and dnf_result.rc == 1 and 'Failed to install' in dnf_result.msg) or dnf_result.skipped is defined or \
        ((dnf_result.changed and dnf_result.failed) and (not dnf_result.changed))"
    - "go_result.rc is defined and go_result.rc != 0"
  failed_when: false

- name: "Ensure {{ software_item }} is installed (Binary)"
  get_url:
    url: "{{ software_package[software_item]['binary'] }}"
    dest: "/usr/local/bin/{{ software_item }}"
    mode: 0755
  when:
    - "'binary' in available_methods"
    - "(dnf_result.rc is defined and dnf_result.rc == 1 and 'Failed to install' in dnf_result.msg) or dnf_result.skipped is defined or \
        ((dnf_result.changed and dnf_result.failed) and (not dnf_result.changed))"
    - "go_result.rc is defined and go_result.rc != 0"
    - "'is already installed' not in cargo_result.stderr or 'Installed package' not in cargo_result.stderr or 'error: could not find' in cargo_result.stderr"
  register: binary_result
  failed_when: "binary_result.status_code != 200 and 'Request failed' not in binary_result.msg"

- name: "Ensure {{ software_item }} is installed (snap)"
  snap:
    name: "{{ software_package[software_item]['snap'] }}"
    state: present
  when:
    - "'snap' in available_methods"
    - "(dnf_result.rc is defined and dnf_result.rc == 1 and 'Failed to install' in dnf_result.msg) or dnf_result.skipped is defined or \
        ((dnf_result.changed and dnf_result.failed) and (not dnf_result.changed))"
    - "go_result.rc is defined and go_result.rc != 0"
    - "'is already installed' not in cargo_result.stderr or 'Installed package' not in cargo_result.stderr or 'error: could not find' in cargo_result.stderr"
    - "(binary_result.msg is defined and 'Request failed' in binary_result.msg) or binary_result.skipped is defined or \
        ((binary_result.changed and binary_result.failed) and (not binary_result.changed))"
  register: snap_result
  failed_when: "snap_result.msg is defined and 'No snap matching' not in snap_result.msg"

- name: "Ensure {{ software_item }} is installed (GitHub)"
  include_role:
    name: githubbinary
  vars:
    github_binaries:
      - "{{ software_package[software_item]['github'] }}"
  when:
    - "'github' in available_methods"
    - "(dnf_result.rc is defined and dnf_result.rc == 1 and 'Failed to install' in dnf_result.msg) or dnf_result.skipped is defined or \
        ((dnf_result.changed and dnf_result.failed) and (not dnf_result.changed))"
    - "go_result.rc is defined and go_result.rc != 0"
    - "'is already installed' not in cargo_result.stderr or 'Installed package' not in cargo_result.stderr or 'error: could not find' in cargo_result.stderr"
    - "(binary_result.msg is defined and 'Request failed' in binary_result.msg) or binary_result.skipped is defined or \
        ((binary_result.changed and binary_result.failed) and (not binary_result.changed))"
    - snap_result.msg is defined or snap_result.skipped is defined or ((snap_result.changed and snap_result.failed) and (not snap_result.changed))
