#!/bin/bash

# CHANNEL may be set by envsubst
CHANNEL="${CHANNEL:-main}"

# --- TUI helpers (show_success/show_error adapted from bash-tui-toolkit, Apache-2.0) ---

# Detect whether the terminal supports colors and Unicode
_tui_fancy=false
if [[ -t 2 ]] && [[ "${TERM:-dumb}" != "dumb" ]]; then
    _tui_fancy=true
fi

if $_tui_fancy; then
    readonly _GREEN='\033[0;32m' _RED='\033[0;31m' _BLUE='\033[0;34m' _BOLD='\033[1m' _RESET='\033[0m'
    readonly _CHECK='✔' _CROSS='✘' _INFO='ℹ'
    readonly _SPINNER_FRAMES=(⠋ ⠙ ⠹ ⠸ ⠼ ⠴ ⠦ ⠧ ⠇ ⠏)
else
    readonly _GREEN='' _RED='' _BLUE='' _BOLD='' _RESET=''
    readonly _CHECK='OK' _CROSS='FAIL' _INFO='--'
    readonly _SPINNER_FRAMES=()
fi

show_success() { echo -e "${_GREEN}${_CHECK}${_RESET} $1" >&2; }
show_error()   { echo -e "${_RED}${_CROSS}${_RESET} $1" >&2; }
show_info()    { echo -e "${_BLUE}${_INFO}${_RESET} $1" >&2; }
show_header()  { echo -e "\n${_BOLD}$1${_RESET}\n" >&2; }

# Run a command, hiding output unless it fails.
# On a fancy terminal a spinner is shown; otherwise just a static "..." line.
# Usage: run_step "Description" command [args...]
run_step() {
    local desc="$1"
    shift
    local tmpfile spin_stop spin_pid=""
    tmpfile=$(mktemp)
    spin_stop=$(mktemp)

    # Clean up spinner on interrupt or exit
    _stop_spinner() {
        if [[ -n "$spin_pid" ]]; then
            rm -f "$spin_stop"
            wait "$spin_pid" 2>/dev/null
            spin_pid=""
            printf '\r\033[K' >&2
        fi
    }
    trap '_stop_spinner; rm -f "$tmpfile"; exit 130' INT TERM

    if $_tui_fancy; then
        # Start spinner in background - uses a flag file instead of kill
        # to avoid a race where the signal arrives before the subshell is ready
        (
            trap '' INT TERM
            local i=0
            while [[ -f "$spin_stop" ]]; do
                printf '\r  %s %s' "${_SPINNER_FRAMES[i%${#_SPINNER_FRAMES[@]}]}" "$desc" >&2
                i=$((i + 1))
                sleep 0.1
            done
        ) &
        spin_pid=$!
    else
        echo "  ... $desc" >&2
    fi

    # Run the actual command, capturing all output
    "$@" > "$tmpfile" 2>&1
    local exit_code=$?

    # Stop spinner and clear the line
    _stop_spinner
    trap - INT TERM

    if [[ $exit_code -eq 0 ]]; then
        show_success "$desc"
    else
        show_error "$desc"
        echo "" >&2
        cat "$tmpfile" >&2
        echo "" >&2
        rm -f "$tmpfile"
        exit 1
    fi

    rm -f "$tmpfile"
    return 0
}

detect_os() {
    ARCH=$(uname -m)

    if [ -f /etc/os-release ]; then
        . /etc/os-release
        OS=$ID
        OS_VERSION=$VERSION_ID
        OS_FAMILY=$ID_LIKE
    elif [ -f /etc/redhat-release ]; then
        OS="rhel"
        OS_VERSION=$(rpm -E %{rhel})
    elif [ -f /etc/debian_version ]; then
        OS="debian"
        OS_VERSION=$(cat /etc/debian_version)
    else
        return 1
    fi

    if [[ "$OS" == "ubuntu" || "$OS" == "debian" || "$OS_FAMILY" == *"debian"* ]]; then
        OS_TYPE="debian"
    elif [[ "$OS" == "rhel" || "$OS" == "centos" || "$OS" == "rocky" || "$OS" == "almalinux" ||
        "$OS" == "fedora" || "$OS" == "amzn" || $ID == "scientific" || $ID == "ol" ||
        "$OS_FAMILY" == *"rhel"* || "$OS_FAMILY" == *"fedora"* ]]; then
        OS_TYPE="rhel"
    elif [[ "$OS" == "sles" || "$OS" == "opensuse-leap" || "$OS_FAMILY" == *"suse"* ]]; then
        OS_TYPE="suse"
    elif [[ "$OS" == "arch" || "$OS" == "manjaro" ]]; then
        OS_TYPE="arch"
    else
        return 1
    fi

}

# Find the closest available release for a given codename
find_closest_release() {
    local version_codename="$1"
    shift
    local available=("$@")

    declare -A release_dates=(
        # Debian releases
        ["buster"]="201013"   # Debian 10
        ["bullseye"]="202108" # Debian 11
        ["bookworm"]="202306" # Debian 12
        ["trixie"]="202506"   # Debian 13
        ["sid"]="999999"      # Debian unstable (always latest)

        # Ubuntu LTS releases
        ["focal"]="202004" # Ubuntu 20.04 LTS - April 2020
        ["jammy"]="202204" # Ubuntu 22.04 LTS - April 2022
        ["noble"]="202404" # Ubuntu 24.04 LTS - April 2024

        # Ubuntu interim releases
        ["groovy"]="202010"   # Ubuntu 20.10
        ["hirsute"]="202104"  # Ubuntu 21.04
        ["impish"]="202110"   # Ubuntu 21.10
        ["kinetic"]="202210"  # Ubuntu 22.10
        ["lunar"]="202304"    # Ubuntu 23.04
        ["mantic"]="202310"   # Ubuntu 23.10
        ["oracular"]="202410" # Ubuntu 24.10
        ["plucky"]="202504"   # Ubuntu 25.04
    )

    for target in "${available[@]}"; do
        if [[ "$version_codename" == "$target" ]]; then
            echo "$target"
            return 0
        fi
    done

    local input_date="${release_dates[$version_codename]}"

    if [[ -z "$input_date" ]]; then
        echo "${available[-1]}"
        return 0
    fi

    local best_match=""
    local best_date="0"

    for target in "${available[@]}"; do
        local target_date="${release_dates[$target]}"

        if [[ "$target_date" -le "$input_date" ]] && [[ "$target_date" -gt "$best_date" ]]; then
            best_match="$target"
            best_date="$target_date"
        fi
    done

    if [[ -z "$best_match" ]]; then
        echo "${available[0]}"
    else
        echo "$best_match"
    fi
}

get_release_for_debian_distro() {
    if [ -z "$VERSION_CODENAME" ]; then
        echo "Unsupported OS: $OS (Type: $OS_TYPE, Version: $OS_VERSION, Arch: $ARCH)" >&2
        exit 1
    fi

    case "$OS" in
    ubuntu)
        find_closest_release "$VERSION_CODENAME" focal jammy noble
        ;;
    debian)
        find_closest_release "$VERSION_CODENAME" bullseye bookworm
        ;;
    *)
        echo "Unsupported OS: $OS (Type: $OS_TYPE, Version: $OS_VERSION, Arch: $ARCH)" >&2
        exit 1
        ;;
    esac
}

add_redhat_repo() {
    sudo rpm --import https://packages.knocknoc.io/key/knocknoc_public_key.asc

    local url="https://packages.knocknoc.io/redhat/"
    if [[ "beta" != "main" ]]; then
        url="https://packages.knocknoc.io/redhat-beta/"
    fi

    sudo tee /etc/yum.repos.d/knocknoc.repo <<EOF
[knocknoc]
name=Knocknoc Repository
baseurl=$url
enabled=1
gpgcheck=1
gpgkey=https://packages.knocknoc.io/key/knocknoc_public_key.asc
EOF

}

add_debian_repo() {
    sudo mkdir -p /etc/apt/keyrings

    # Fetch and add the repo signing keyring (contains all trusted signing keys)
    curl -fsSL https://packages.knocknoc.io/key/knocknoc_public_key.asc | sudo tee /etc/apt/keyrings/knocknoc-pub.asc > /dev/null
    echo "deb [signed-by=/etc/apt/keyrings/knocknoc-pub.asc arch=amd64] https://packages.knocknoc.io/$OS $(get_release_for_debian_distro) beta" | sudo tee /etc/apt/sources.list.d/knocknoc.list
}

install_package() {
    PACKAGE_NAME=knocknoc

    if [[ "$OS_TYPE" == "debian" ]]; then
        sudo apt install -y $PACKAGE_NAME
    else
        sudo yum install -y $PACKAGE_NAME
    fi
}

# ============================================================================
# Installer flow
# ============================================================================

show_header "Knocknoc Installer"

# --- Step 1: EULA ---
while true; do
    echo ""
    echo "Have you already read the End-User Licence Agreement? [1/2]:"
    echo "  1) Yes, accept"
    echo "  2) No, read it first"
    echo ""
    read -p "Select [1/2] (default: 1): " eula_choice </dev/tty
    eula_choice=${eula_choice:-"1"}

    if [[ "$eula_choice" == "1" ]]; then
        show_success "Licence accepted"
        break
    elif [[ "$eula_choice" == "2" ]]; then

echo "
KNOCKNOC - END USER LICENCE AGREEMENT

This End User Licence Agreement (Agreement) is between Knocknoc Pty Ltd
(ACN 656 951 549) of 18 Lexington Drive, Bella Vista NSW 2153 (Knocknoc) and
the person or entity accepting this Agreement (Licensee).

By clicking 'I agree', completing an order, signing a quote, or by downloading,
installing or accessing the Software, the Licensee agrees to be bound by this
Agreement. If the Licensee is acting on behalf of a company or other legal
entity, it represents that it has authority to bind that entity.

This EULA applies unless you have a separate written licence agreement with
Knocknoc for the Software, in which case that agreement prevails to the extent
of any conflict.

If the Licensee does not agree to this Agreement, it must not download, install
or use the Software.


1   DEFINITIONS
--------------------------------------------------------------------------------

    In this Agreement, unless the context requires otherwise:

    Agreement means this End User Licence Agreement, including any Order Form.

    Authorised Users means the individuals the Licensee designates to use the
        Software, as specified in the Order Form or the Licensee's account, who
        may include employees, contractors and agents of the Licensee.

    Business Day means a day that is not a Saturday, Sunday or public holiday in
        New South Wales, Australia.

    Commencement Date means the earlier of: (a) the date the Licensee first
        accesses or downloads the Software; and (b) the date of any applicable
        Order Form.

    Confidential Information means information disclosed by one party to the
        other that is identified as confidential or that ought reasonably to be
        treated as confidential given its nature or the circumstances of
        disclosure, and includes the terms of this Agreement and all Licensee
        Data. It does not include information that is or becomes publicly
        available other than through a breach of this Agreement.

    Documentation means any user guides, technical specifications and other
        materials that Knocknoc makes available for the Software.

    Fees means the licence fees payable by the Licensee as set out in the Order
        Form or on the Knocknoc website at the time of purchase.

    Hosted Deployment means a deployment where Knocknoc hosts the server-side
        component of the Software on infrastructure operated by or on behalf of
        Knocknoc.

    IP Rights means all intellectual property rights, including copyright,
        patents, trademarks, designs, know-how and trade secrets, whether
        registered or unregistered.

    Licence has the meaning given in clause 2.1.

    Licensee Data means data, content or information that the Licensee or its
        Authorised Users submit to or generate through the Software.

    Licensing Portal means https://licensing.knocknoc.io

    On-Premises Deployment means a deployment where the Licensee installs and
        operates the Software on its own infrastructure.

    On-Premises Single User Licence means a licence of the Software subject to
        the terms set out in clause 3.

    Order Form means a written order, proposal or quote agreed between the
        parties setting out the Fees, deployment model, subscription term and
        any other agreed terms.

    Reseller means a third party authorized by Knocknoc to resell or distribute
        the Software to end users.

    Privacy Act means the Privacy Act 1988 (Cth).

    Software means the Knocknoc network allowlisting platform known as
        'Knocknoc' (including the Knocknoc Agent and Operations & Management
        Toolbox), together with any updates, upgrades and new releases that
        Knocknoc makes available to the Licensee under this Agreement.

    Subscription Term means the period for which the Licence is granted, as
        specified in the Order Form or, for online purchases, as selected by the
        Licensee at the time of purchase.

    Support Services means the support and maintenance services described in
        clause 12.

    Trust Center means the Knocknoc Trust Center located at
        https://trust.knocknoc.io/


2   LICENCE GRANT
--------------------------------------------------------------------------------

    2.1   Subject to the Licensee's compliance with this Agreement and payment
          of the Fees, Knocknoc grants the Licensee a non-exclusive,
          non-transferable, non-sublicensable licence to install and use the
          Software during the Subscription Term solely for the Licensee's own
          internal business purposes (Licence).

    2.2   The Licence covers the deployment model selected by the Licensee:
          On-Premises Deployment, Hosted Deployment, or both, as specified in
          the Order Form or the Licensee's account.

    2.3   The Licensee may only permit its Authorised Users to access and use
          the Software on its behalf.

    2.4   The Licensee may only deploy the number of copies of the Software as
          expressly specified on the Order Form or as purchased through
          Knocknoc's website.

    2.5   The Licensee is responsible for its Authorised Users' compliance with
          this Agreement.

    2.6   This Agreement sets out Knocknoc's standard licence terms. Where an
          Order Form is in place, any inconsistency between this Agreement and
          the Order Form is resolved in favour of the Order Form.

    2.7   Where the Licensee acquires the Software through a Reseller, this
          Agreement governs the Licensee's use of the Software. Acceptance of
          this Agreement by the Licensee (whether by click-through or otherwise)
          binds the Licensee directly to Knocknoc on these terms.


3   FREE SINGLE-USER LICENCE
--------------------------------------------------------------------------------

    3.1   If the Licensee has selected an On-Premises Single User Licence
          Knocknoc grants the Licensee a free licence to install and use the
          Software for one user on a single device for the Licensee's personal,
          non-commercial use only, subject to the terms of this EULA
          (Free Licence).

    3.2   The Free Licence is personal to the Licensee, and the Licensee must
          not without Knocknoc's prior written agreement (a) use the Software
          for any commercial purpose or for any public display (whether
          commercial or non-commercial); (b) share, transfer, sublicence or
          otherwise make the Software available to any other person; or
          (c) install or run more than one instance of the Software under the
          Free Licence.

          3.2.1   The term of the Free Licence is 6 months but may be renewed by
                  the Licensee requesting a new key in the Licensing Portal.
                  Knocknoc may terminate the Free Licence at any time on written
                  notice, and it terminates automatically if the Licensee
                  breaches any term of this EULA.

    3.3   For the avoidance of doubt, the Software is provided under the Free
          Licence on an \"as is\" basis and Knocknoc makes no warranties in
          connection with the Free Licence beyond those that cannot be excluded
          by law.


4   RESTRICTIONS ON USE
--------------------------------------------------------------------------------

    4.1   The Licensee must (a) use the Software only as permitted under this
          Agreement; (b) ensure that only Authorised Users access the Software;
          (c) keep its account credentials confidential and notify Knocknoc
          promptly if it suspects any unauthorised access; and (d) keep its
          account and contact information current.

    4.2   The Licensee must not (a) copy, modify, adapt, translate or create
          derivative works of the Software; (b) reverse engineer, decompile,
          disassemble or otherwise attempt to derive the source code of the
          Software; (c) sell, sublicence, transfer, assign or otherwise dispose
          of the Software or any rights in it to a third party without
          Knocknoc's prior written consent; (d) use the Software to build a
          competing product or service or for competitive benchmarking without
          Knocknoc's written consent; (e) remove or alter any copyright or
          proprietary notices on the Software; or (f) use the Software in any
          way that violates applicable law.


5   FEES AND PAYMENT
--------------------------------------------------------------------------------

    5.1   The Licensee must pay the Fees in advance in the currency and at the
          intervals specified in the Order Form or, for online purchases, as
          selected at the time of purchase. Where no currency is specified, all
          amounts are deemed to be in USD.

    5.2   All invoices are due and payable within 30 days of the invoice date.
          Failure to pay on time is a material breach of this Agreement.

    5.3   Where the Licensee pays by direct debit or recurring charge, it
          authorises Knocknoc to charge the nominated payment method at the
          agreed intervals for the duration of the Subscription Term.

    5.4   All Fees are exclusive of taxes. The Licensee is responsible for all
          applicable taxes, levies or duties imposed by any taxing authority in
          connection with this Agreement, including goods and services tax
          (GST), value added tax (VAT), sales tax, withholding tax and any
          similar charge (Taxes), other than taxes imposed on Knocknoc's net
          income. Where Knocknoc is required by law to collect Taxes, Knocknoc
          will add them to the applicable invoice at the prevailing rate and the
          Licensee must pay them. If the Licensee is required by law to withhold
          any Taxes from payments to Knocknoc, the Licensee must gross up the
          payment so that Knocknoc receives the full amount of the applicable
          Fee. Each party is responsible for its own income taxes and equivalent
          levies.

    5.5   Where the Licensee acquires the Software through an authorised
          reseller (Reseller): (a) the Licensee's payment obligations are owed
          to the Reseller, not to Knocknoc, and are governed by the Licensee's
          agreement with the Reseller; (b) Knocknoc's obligations under this
          Agreement run directly to the Licensee; (c) the Licensee's use of the
          Software remains subject to this Agreement in full; and (d) Knocknoc
          is not responsible for any acts or omissions of the Reseller,
          including the Reseller's failure to remit payment to Knocknoc.

    5.6   Knocknoc may suspend access to the Software if any payment is overdue
          by more than 30 days, having given the Licensee at least 5 Business
          Days' written notice of the overdue amount.

    5.7   If the Licensee fails to pay any amount by the due date, Knocknoc may
          charge interest on the overdue amount at the rate of 1% per month,
          calculated daily from the due date until the date of actual payment,
          compounded monthly. Knocknoc may apply any payment received first to
          accrued interest before reducing the outstanding principal.

    5.8   Except as expressly set out in this Agreement or any applicable Order
          Form, Fees are non-refundable and non-cancellable.


6   SUBSCRIPTION TERM AND RENEWAL
--------------------------------------------------------------------------------

    6.1   The Subscription Term commences on the Commencement Date and continues
          for the period specified in the Order Form or selected at the time of
          online purchase.

    6.2   Unless either party gives written notice of non-renewal at least
          30 days before the end of the then-current Subscription Term, the
          Licence will automatically renew for a further period of the same
          duration, up to a maximum of one year, at Knocknoc's then-current
          pricing.

    6.3   For annual subscriptions Knocknoc will give the Licensee at least
          30 days' written notice before any renewal, confirming the renewal
          date and applicable Fees.


7   ON-PREMISES DEPLOYMENT
--------------------------------------------------------------------------------

    7.1   This clause 7 applies where the Licensee selects an On-Premises
          Deployment.

    7.2   The Licensee is responsible for providing and maintaining the
          hardware, operating environment and network infrastructure required
          to operate the Software.

    7.3   Knocknoc does not host or store Licensee Data in an On-Premises
          Deployment. The Licensee is solely responsible for the security and
          backup of its own infrastructure and data.

    7.4   Knocknoc will provide the Support Services described in clause 12 in
          respect of the On-Premises Deployment.


8   HOSTED DEPLOYMENT
--------------------------------------------------------------------------------

    8.1   This clause 8 applies where the Licensee selects a Hosted Deployment.

    8.2   Knocknoc will use commercially reasonable efforts to make the hosted
          environment available. Any specific uptime commitments will be set out
          in a separate service level agreement (SLA) set out in the Order Form,
          or as otherwise agreed in writing between the parties. Where no SLA is
          in place, Knocknoc does not warrant any specific level of
          availability.

    8.3   Knocknoc will implement reasonable technical, physical and
          organisational security measures to protect Licensee Data hosted on
          its infrastructure from unauthorized access, destruction, use,
          modification or disclosure as set out in Knocknoc's Trust Center.

    8.4   Knocknoc will process Licensee Data only to provide the hosted service
          and will not use it for any other purpose unless otherwise agreed in
          writing with the Licensee.

    8.5   For license verification purposes, Knocknoc may collect usage data,
          including the number of licenses used, active and periodic login
          counts (without user data), and product utilization and configuration
          details. This data does not include any Licensee Data or user
          information.

    8.6   On termination or expiry of this Agreement, for a Hosted Deployment
          Knocknoc will provide the Licensee a reasonable period (not less than
          30 days) to export or retrieve its Licensee Data before it is deleted
          from Knocknoc's systems. Knocknoc will delete Licensee Data within
          60 days of that period ending.

    8.7   Knocknoc is not responsible for failures of third-party infrastructure
          (including cloud providers, internet service providers or
          telecommunications networks) that are outside its reasonable control.


9   LICENSEE DATA AND PRIVACY
--------------------------------------------------------------------------------

    9.1   Licensee Data remains the Licensee's property. Knocknoc acquires no
          right, title or interest in Licensee Data other than the right to use
          it to provide the services under this Agreement.

    9.2   Knocknoc's Privacy Policy, available at knocknoc.io/legal, sets out how
          Knocknoc handles personal information. By using the Software, the
          Licensee acknowledges it has read the Privacy Policy.

    9.3   The Licensee is responsible for obtaining any consents or
          authorisations required under applicable law in relation to Licensee
          Data before submitting it to the Software.


10  DATA PROTECTION
--------------------------------------------------------------------------------

    10.1  This clause applies in addition to clause 9 (Licensee Data and
          Privacy) where the Licensee is subject to a data protection law that
          requires a data processing agreement to be in place before a data
          processor may process personal data on behalf of a data controller
          (including the General Data Protection Regulation (EU) 2016/679
          (GDPR), the UK GDPR, and equivalent legislation in other
          jurisdictions) (each a Data Protection Law).

    10.2  Where the Licensee determines that a Data Protection Law applies to
          the processing of personal data by Knocknoc under this Agreement, the
          Licensee may request that the parties enter into a separate data
          processing agreement (DPA). Knocknoc will negotiate and enter into a
          DPA in good faith on request. Until a DPA is executed, Knocknoc will
          process personal data only to the extent necessary to provide the
          services under this Agreement and in accordance with the Licensee's
          documented instructions.

    10.3  The Licensee is solely responsible for determining whether a Data
          Protection Law applies to its use of the Software and for notifying
          Knocknoc accordingly. Knocknoc is not liable for any failure by the
          Licensee to request a DPA where one is required under applicable law.


11  SECURITY INCIDENTS
--------------------------------------------------------------------------------

    11.1  This clause applies to the Hosted Deployment. If Knocknoc becomes
          aware of a security incident that results in, or is reasonably likely
          to result in, unauthorised access to, disclosure of, or loss of
          Licensee Data (Security Incident), Knocknoc will: (a) notify the
          Licensee in writing without undue delay and, where feasible, within
          72 hours of becoming aware of the Security Incident; (b) provide the
          Licensee with sufficient information to allow the Licensee to meet any
          notification obligations it may have under applicable law, including
          the nature of the incident, the categories and approximate volume of
          data affected, and the steps Knocknoc is taking in response; and
          (c) take prompt steps to contain, investigate and remediate the
          Security Incident.

    11.2  Knocknoc's notification of a Security Incident does not constitute an
          admission of fault or liability.


12  SUPPORT SERVICES
--------------------------------------------------------------------------------

    12.1  For all paid subscriptions, subject to payment of the applicable Fees,
          Knocknoc will:

          a.  provide the Support Services included in the Licensee's
              subscription tier as described on the Knocknoc website or in the
              Order Form; and

          b.  provide remote maintenance and support services available during
              Knocknoc's usual working hours via e-mail (accessible through the
              Licensing Portal) to resolve problems materially affecting the
              operation of the Software on a best effort basis.

    12.2  Knocknoc may update, modify or provide patches to the Software from
          time to time. Where an update is material, Knocknoc will use
          reasonable commercial endeavours to give the Licensee reasonable
          advance notice. For On-Premises Deployment the Licensee is responsible
          for obtaining and installing updates and patches from the Licensing
          Portal.

    12.3  Support Services do not cover issues caused by: (a) modifications made
          to the Software by the Licensee; (b) use of the Software other than as
          permitted under this Agreement; or (c) third-party hardware, software
          or services not provided by Knocknoc.


13  INTELLECTUAL PROPERTY
--------------------------------------------------------------------------------

    13.1  The Software is licenced, not sold, to the Licensee. Knocknoc owns all
          IP Rights in the Software, Documentation and any improvements or
          derivative works, including any customisations developed at the
          Licensee's request. Nothing in this Agreement transfers any IP Rights
          in the Software to the Licensee.

    13.2  The Licensee retains all IP Rights in the Licensee Data.

    13.3  If the Licensee or its Authorised Users provide any suggestions,
          ideas, enhancement requests, feedback, recommendations or other
          information relating to the Software or Documentation (Feedback), the
          Licensee assigns to Knocknoc all IP Rights in that Feedback. Knocknoc
          may use Feedback for any purpose, including developing, modifying or
          improving the Software, without restriction and without any obligation
          to pay compensation or give attribution to the Licensee.

    13.4  The Software may incorporate open-source software components
          (Open Source Components). Those components are licensed to the
          Licensee under the terms of the applicable open-source licences, not
          under this Agreement. Knocknoc's IP warranty in clause 16.1 does not
          extend to Open Source Components. Where an open-source licence requires
          Knocknoc to make source code available, Knocknoc will do so on request
          or by publication in the Knocknoc Trust Center.

    13.5  If a third party alleges that the Software, as provided by Knocknoc,
          infringes that third party's IP Rights (IP Claim):

          a.  the Licensee must: (i) notify Knocknoc immediately in writing of
              the IP Claim; (ii) give Knocknoc sole control of the defence and
              settlement of that IP Claim; and (iii) provide Knocknoc with
              reasonable assistance and information in connection with the IP
              Claim;

          b.  subject to the Licensee's compliance with clause 13.5a Knocknoc
              will indemnify the Licensee from and against any claim,
              proceeding, loss, damage or expense (including reasonable legal
              costs) arising from the IP Claim; and

          c.  Knocknoc may, at its election and cost: (a) obtain a licence for
              the Licensee to continue using the Software; (b) modify the
              Software to remove the infringement; or (c) terminate the affected
              Licence and refund any prepaid Fees for the unexpired Subscription
              Term.

    13.6  Clause 13.5 does not apply where the infringement arises from:
          (a) modification of the Software by the Licensee; (b) use of the
          Software in combination with third-party products not approved by
          Knocknoc; or (c) use of the Software in a manner not permitted under
          this Agreement.

    13.7  This clause 13 sets out Knocknoc's entire liability for IP
          infringement claims.


14  CONFIDENTIALITY
--------------------------------------------------------------------------------

    14.1  Each party must keep the other's Confidential Information strictly
          confidential and must not disclose it to any third party without the
          other's prior written consent, except as permitted under this clause.

    14.2  Each party may disclose the other's Confidential Information to its
          employees, contractors and advisers who need to know it for the
          purposes of this Agreement and who are bound by confidentiality
          obligations at least as protective as this clause.

    14.3  A party may disclose Confidential Information to the extent required by
          law or a court or regulatory authority of competent jurisdiction,
          provided it gives the other party prompt written notice (to the extent
          permitted by law) and cooperates with the other party's reasonable
          efforts to seek a protective order.

    14.4  Confidentiality obligations survive termination or expiry of this
          Agreement for a period of five years.

    14.5  If Knocknoc and the Licensee have executed a separate non-disclosure
          agreement, the terms of that agreement will prevail to the extent of
          any inconsistency with this Agreement.


15  AUDIT
--------------------------------------------------------------------------------

    15.1  Knocknoc may verify the Licensee's compliance with this Agreement by
          conducting an audit of the Licensee's use of the Software, subject to
          the conditions in this clause 15.

    15.2  Any audit will be: (a) conducted on at least 10 Business Days' prior
          written notice; (b) limited to matters directly relevant to the
          Licensee's compliance with this Agreement; (c) conducted no more than
          once per calendar year, unless a prior audit has revealed a material
          breach; and (d) conducted in a manner that minimises disruption to the
          Licensee's operations.

    15.3  Knocknoc bears the cost of any audit, provided that if an audit
          reveals that the Licensee has underpaid Fees, the Licensee must pay
          the shortfall within 30 days, and Knocknoc may invoice and the
          Licensee must pay the reasonable costs of that audit.

    15.4  Any audit will be conducted by Knocknoc personnel or an independent
          third party bound by confidentiality obligations.


16  WARRANTIES
--------------------------------------------------------------------------------

    16.1  Knocknoc warrants that: (a) it has the right to grant the Licence;
          (b) the Software will perform materially in accordance with the
          Documentation during the Subscription Term; (c) it will provide the
          Support Services with reasonable care and skill; and (d) Knocknoc will
          use reasonable efforts designed to ensure that the Software, when and
          as provided by Knocknoc, is free of any viruses, malware or similar
          malicious code (each a \"Performance Warranty\").

    16.2  If the Software fails to perform materially in accordance with the
          Documentation, the Licensee must promptly notify Knocknoc in writing.
          Knocknoc's sole obligation is to use reasonable efforts to correct the
          non-conformance within a reasonable time. If Knocknoc is unable to do
          so, the Licensee may terminate the affected subscription and receive a
          pro-rata refund of any prepaid Fees which will be the Licensee's
          exclusive remedy and Knocknoc's entire liability for breach of a
          Performance Warranty.

    16.3  Except as expressly provided in this clause 16, the Software, Support
          Services and Documentation are provided \"AS IS.\" Knocknoc makes no other
          warranties, whether express, implied, statutory or otherwise,
          including warranties of merchantability, fitness for a particular
          purpose, title or non-infringement. Knocknoc does not warrant that the
          Licensee's use of the Software will be uninterrupted or error-free.

    16.4  Knocknoc is not liable for delays, failures or problems inherent in
          use of the internet and electronic communications or other systems
          outside Knocknoc's control.

    16.5  Nothing in this Agreement excludes, restricts or modifies any right or
          remedy, or any guarantee, warranty, term or condition implied or
          imposed by any legislation that cannot lawfully be excluded or
          limited. If any such legislation applies, Knocknoc limits its
          liability (to the extent it lawfully can) to the re-supply of the
          relevant services or the cost of having them re-supplied.


17  THIRD-PARTY SOFTWARE
--------------------------------------------------------------------------------

    17.1  The Software may interoperate with or be used in conjunction with
          third-party software, platforms or services not provided by Knocknoc
          (Third-Party Software). Knocknoc does not warrant, support or take
          responsibility for any Third-Party Software. The Licensee's use of
          Third-Party Software is at its own risk and is governed solely by the
          terms and conditions of the relevant third party.

    17.2  Knocknoc is not liable for any loss, damage or claim arising from the
          Licensee's use of Third-Party Software or from any failure,
          unavailability or change in any Third-Party Software that affects the
          operation of the Software.


18  LIMITATION OF LIABILITY
--------------------------------------------------------------------------------

    18.1  To the maximum extent permitted by law, neither party is liable to the
          other for any indirect, consequential, incidental, special or punitive
          loss or damage, or for any loss of profits, revenue, data, business or
          anticipated savings, arising out of or in connection with this
          Agreement, even if that party has been advised of the possibility of
          such loss.

    18.2  To the maximum extent permitted by law, Knocknoc's total aggregate
          liability to the Licensee for all claims arising out of or in
          connection with this Agreement is limited to the Fees paid by the
          Licensee in the 12 months immediately before the event giving rise to
          the claim.

    18.3  The limitations in clauses 18.1 and 18.2 do not apply to: (a) death or
          personal injury caused by negligence; (b) fraud or fraudulent
          misrepresentation; (c) wilful misconduct; (d) Knocknoc's obligations
          under clause 13.5 (IP indemnity); or (e) any liability that cannot be
          limited by law.


19  EXPORT CONTROLS
--------------------------------------------------------------------------------

    19.1  The Software may be subject to export control laws and regulations,
          including those of Australia, the United States and other
          jurisdictions. The Licensee must comply with all applicable export
          control laws and must not export, re-export, transfer or make
          available the Software, directly or indirectly, to any country,
          territory, person or entity where doing so would be prohibited or
          would require a licence, authorisation or approval that has not been
          obtained.

    19.2  The Licensee represents and warrants that it is not located in, under
          the control of, or a national or resident of any country subject to
          applicable trade sanctions, and that it is not on any prohibited
          persons list maintained by any relevant government authority.

    19.3  The Software is a \"commercial item\" as that term is defined at
          FAR 2.101, consisting of \"commercial computer software\" and
          \"commercial computer software documentation\" as such terms are used in
          FAR 12.212 and DFARS 227.7202. If the Software is acquired by or on
          behalf of any agency of the U.S. Government, the U.S. Government's
          rights in the Software are limited to those rights specified in this
          Agreement, pursuant to FAR 12.212 and DFARS 227.7202-1 through
          227.7202-4 (as applicable) for defence agencies, and pursuant to
          FAR 52.227-19 for civilian agencies. This applies whether the
          acquisition is direct or through a contractor or subcontractor acting
          on the U.S. Government's behalf.


20  TERM AND TERMINATION
--------------------------------------------------------------------------------

    20.1  This Agreement commences on the Commencement Date and continues until
          the end of the Subscription Term, unless terminated earlier in
          accordance with this clause.

    20.2  Either party may terminate this Agreement on 30 days' written notice
          to the other party if the other party commits a material breach and
          fails to remedy that breach within the 30 day notice period.

    20.3  Knocknoc may terminate this Agreement immediately on written notice if:
          (a) the Licensee fails to pay any Fees that remain unpaid 14 days
          after written notice of the overdue amount; or (b) if in Knocknoc's
          opinion the Licensee becomes insolvent within the meaning of section
          95A of the Corporations Act 2001 (Cth), goes into liquidation or makes
          any arrangement with its creditors generally.

    20.4  The Licensee may terminate this Agreement for convenience on 60 days'
          written notice. Prepaid Fees are non-refundable on convenience
          termination.

    20.5  On termination or expiry: (a) all Licences granted under this
          Agreement terminate immediately; (b) the Licensee must cease using the
          Software and, on request, confirm in writing that it has done so; and
          (c) clause 8.6 applies in respect of any Hosted Deployment.

    20.6  Clauses that by their nature survive termination or expiry will
          continue to apply, including without limitation: Licensee Data and
          Privacy; Intellectual Property; Confidentiality; Third-Party Software;
          Limitation of Liability; Security Incidents; Export Controls; Data
          Protection; and General.


21  DISPUTES
--------------------------------------------------------------------------------

    21.1  If a dispute arises out of or in connection with this Agreement
          (including any question about its existence, validity or termination),
          the parties must follow this process before commencing any legal
          proceedings (except where a party seeks urgent interlocutory relief).

    21.2  The party claiming a dispute exists must give the other party written
          notice setting out the nature of the dispute and the outcome sought
          (Dispute Notice).

    21.3  Within 10 Business Days of a Dispute Notice being given, a senior
          representative of each party must meet (in person, by telephone or by
          video conference) and attempt in good faith to resolve the dispute.

    21.4  If the dispute is not resolved within 20 Business Days of the Dispute
          Notice (or such longer period as the parties agree in writing), either
          party may commence legal proceedings in accordance with the governing
          law clause of this Agreement.

    21.5  Nothing in this clause prevents either party from seeking urgent
          interlocutory or injunctive relief from a court of competent
          jurisdiction where that party reasonably considers it necessary to
          protect its rights.


22  GENERAL
--------------------------------------------------------------------------------

    22.1  This Agreement is governed by the laws of New South Wales, Australia.
          Each party submits to the non-exclusive jurisdiction of the courts of
          New South Wales.

    22.2  This Agreement (together with any applicable Order Form) is the entire
          agreement between the parties in relation to its subject matter and
          supersedes all prior representations, negotiations and agreements.

    22.3  Knocknoc may update this Agreement from time to time by posting a
          revised version at knocknoc.io/legal. Knocknoc will give the Licensee
          at least 30 days' written notice of any material change. The
          Licensee's continued use of the Software after that notice period
          constitutes acceptance of the updated terms. If the Licensee does not
          accept the updated terms, it may terminate this Agreement before the
          end of the notice period without penalty and Knocknoc will provide a
          pro-rata refund of the remainder of any pre-paid Subscription Term.

    22.4  The Licensee must not assign or transfer this Agreement or any rights
          under it without Knocknoc's prior written consent. Knocknoc may assign
          this Agreement to a related entity or a successor that acquires
          substantially all of Knocknoc's business, provided it gives the
          Licensee written notice.

    22.5  A failure or delay by a party to exercise a right under this Agreement
          does not operate as a waiver of that right. A waiver is only effective
          if given in writing.

    22.6  If any provision of this Agreement is unenforceable, it will be read
          down to the minimum extent necessary to make it enforceable. If it
          cannot be read down, it will be severed, and the remainder of this
          Agreement continues in force.

    22.7  Neither party is liable for any delay or failure to perform its
          obligations (other than a payment obligation) to the extent caused by
          events beyond its reasonable control, including natural disasters,
          acts of government, industrial disputes, or failures of third-party
          infrastructure. The affected party must give prompt written notice and
          use reasonable efforts to overcome or mitigate the effect of the
          event.

    22.8  Notices under this Agreement must be in writing and delivered by email
          (with confirmation of receipt) or by post to the addresses specified
          in the Order Form or the Licensee's account. Notices to Knocknoc must
          be sent to the Knocknoc's address stated at the top of this Agreement
          or the contact details published at knocknoc.io/legal.

================================================================================" | POSIXLY_CORRECT=y more -d

echo ""
echo "Reached end of license - refer to https://packages.knocknoc.io/setup/EULA.txt to retain a copy"

read -p "Do you agree to the above license? [Y/n]: " response </dev/tty
response=${response,,}
if [[ $response != "y" && $response != "" ]]; then
    echo "License not accepted. Exiting."
    exit 1
fi
        show_success "Licence accepted"
        break
    else
        echo "Invalid option. Please enter 1 or 2."
    fi
done

# --- Step 2: Detect OS ---
run_step "Detecting operating system" detect_os
show_info "Detected $OS $OS_VERSION ($OS_TYPE, $ARCH)"

# --- Step 3: Restart journald if needed ---
# Ubuntu 22.04 & 25.04 has a systemd issue where the logs don't work on initial boot unless journald is restarted
if [[ "$OS_TYPE" == "debian" && ("$OS_VERSION" == "22.04" || "$OS_VERSION" == "25.04") ]]; then
    run_step "Restarting journald" bash -c 'sudo systemctl restart systemd-journald && sleep 2'
fi

# --- Step 4: Configure package repository ---
if [[ "$OS_TYPE" == "debian" ]]; then
    if [[ ! -f /etc/apt/sources.list.d/knocknoc.list ]]; then
        run_step "Configuring package repository" add_debian_repo
        run_step "Updating package lists" sudo apt update
    else
        show_info "Knocknoc repository already configured, skipping"
    fi
elif [[ "$OS_TYPE" == "rhel" ]]; then
    if [[ ! -f /etc/yum.repos.d/knocknoc.repo ]]; then
        run_step "Configuring package repository" add_redhat_repo
    else
        show_info "Knocknoc repository already configured, skipping"
    fi
else
    show_error "Unsupported OS: $OS"
    exit 1
fi

# --- Step 5: Install package ---
run_step "Installing Knocknoc" install_package

# --- Step 6: Initial configuration ---
echo ""
show_header "Initial Configuration"
init_args=("-init")
if ! $_tui_fancy; then
    init_args+=("-accessible")
fi
sudo /opt/knocknoc/bin/knocknoc "${init_args[@]}" </dev/tty || exit 1

echo ""
show_success "Knocknoc installation complete"
