#!/bin/bash

# Авторские права (c) 2024 НАЙС СОФТ ГРУПП
# Все права защищены.
# Этот скрипт является собственностью НАЙС СОФТ ГРУПП.
# Краткое описание: реализация lsb_release на bash для отображения информации о дистрибутиве.

# Коды завершения
EXIT_STATUS=0   # Успешное завершение
ERROR_USER=1    # Ошибка пользователя (неверные аргументы)
ERROR_PROGRAM=2 # Ошибка программы (внутренняя ошибка)

MSG_RESULT="" # Переменная для хранения результата вывода

# Функция для отображения справки
Usage() {
  echo -n "
Информация о дистрибутиве.

Использование: lsb_release [опции]

Опции:
  -h, --help         показать это сообщение и выйти
  -i, --id           показать ID дистрибутива
  -d, --description  показать описание дистрибутива
  -r, --release      показать номер релиза дистрибутива
  -c, --codename     показать кодовое имя дистрибутива
  -a, --all          показать всю вышеуказанную информацию
  -s, --short        показать запрошенную информацию в кратком формате
" >&2
  exit ${EXIT_STATUS}
}

# Функция для обработки аргументов командной строки
EnhancedGetopt() {
  NB_ARG="" # Флаг наличия опций для вывода
  local i   # Локальная переменная для цикла

  while [ $# -gt 0 ]; do
    case "$1" in
    -a | --all)
      SHOW_ALL="y"
      NB_ARG="y"
      shift
      ;;
    -c | --codename)
      SHOW_CODENAME="y"
      NB_ARG="y"
      shift
      ;;
    -d | --description)
      SHOW_DESCR="y"
      NB_ARG="y"
      shift
      ;;
    -i | --id)
      SHOW_ID="y"
      NB_ARG="y"
      shift
      ;;
    -r | --release)
      SHOW_REL="y"
      NB_ARG="y"
      shift
      ;;
    -s | --short)
      ARG_S="y"
      shift
      ;;
    -h | --help) Usage ;;
    --)
      shift
      break
      ;;
    -[!-]*)
      for ((i = 1; i < ${#1}; i++)); do
        case "${1:i:1}" in
        a)
          SHOW_ALL="y"
          NB_ARG="y"
          ;;
        c)
          SHOW_CODENAME="y"
          NB_ARG="y"
          ;;
        d)
          SHOW_DESCR="y"
          NB_ARG="y"
          ;;
        i)
          SHOW_ID="y"
          NB_ARG="y"
          ;;
        r)
          SHOW_REL="y"
          NB_ARG="y"
          ;;
        s) ARG_S="y" ;;
        h) Usage ;;
        *)
          echo "Неверная опция: -${1:i:1}" >&2
          EXIT_STATUS=${ERROR_USER}
          Usage
          ;;
        esac
      done
      shift
      ;;
    *)
      echo "Неверная опция: $1" >&2
      EXIT_STATUS=${ERROR_USER}
      Usage
      ;;
    esac
  done
}

# Функция для получения информации из /etc/lsb-release
GetLSBInfo() {
  local lsb_rel_fn="/etc/lsb-release"

  if [ ! -f "${lsb_rel_fn}" ]; then
    echo "ОШИБКА: Файл '${lsb_rel_fn}' не существует." >&2
    exit ${ERROR_PROGRAM}
  fi

  if ! source "${lsb_rel_fn}"; then
    echo "ОШИБКА: Не удалось прочитать '${lsb_rel_fn}'." >&2
    exit ${ERROR_PROGRAM}
  fi
}

# Функция для установки значений по умолчанию, если данные отсутствуют
GetDistribInfo() {
  local MSG_NA="n/a" # Значение по умолчанию для отсутствующих данных

  [ -n "${SHOW_DESCR}" ] && [ -z "${DISTRIB_DESCRIPTION}" ] && DISTRIB_DESCRIPTION="${MSG_NA}"
  [ -n "${SHOW_ID}" ] && [ -z "${DISTRIB_ID}" ] && DISTRIB_ID="${MSG_NA}"
  [ -n "${SHOW_REL}" ] && [ -z "${DISTRIB_RELEASE}" ] && DISTRIB_RELEASE="${MSG_NA}"
  [ -n "${SHOW_CODENAME}" ] && [ -z "${DISTRIB_CODENAME}" ] && DISTRIB_CODENAME="${MSG_NA}"
}

# Функция для вывода идентификатора дистрибутива
DisplayID() {
  if [ -z "${ARG_S}" ]; then
    MSG_RESULT+="ID дистрибутива:\t${DISTRIB_ID}\n"
  else
    MSG_RESULT+="${DISTRIB_ID}\n"
  fi
}

# Функция для вывода описания
DisplayDescription() {
  if [ -z "${ARG_S}" ]; then
    MSG_RESULT+="Описание:\t${DISTRIB_DESCRIPTION}\n"
  else
    MSG_RESULT+="${DISTRIB_DESCRIPTION}\n"
  fi
}

# Функция для вывода номера релиза
DisplayRelease() {
  if [ -z "${ARG_S}" ]; then
    MSG_RESULT+="Релиз:\t${DISTRIB_RELEASE}\n"
  else
    MSG_RESULT+="${DISTRIB_RELEASE}\n"
  fi
}

# Функция для вывода кодового имени
DisplayCodename() {
  if [ -z "${ARG_S}" ]; then
    MSG_RESULT+="Кодовое имя:\t${DISTRIB_CODENAME}\n"
  else
    MSG_RESULT+="${DISTRIB_CODENAME}\n"
  fi
}

# Основная функция для управления логикой скрипта
main() {
  # Если аргументы не переданы, показываем всю информацию
  if [ -z "$1" ]; then
    SHOW_ALL="y"
  else
    EnhancedGetopt "$@"
    # Если указан только --short без других опций, показываем все в кратком формате
    if [ -n "${ARG_S}" ] && [ -z "${NB_ARG}" ]; then
      SHOW_ALL="y"
    fi
  fi

  # Устанавливаем флаги для вывода всех данных, если указана опция -a/--all
  if [ -n "${SHOW_ALL}" ]; then
    [ -z "${SHOW_CODENAME}" ] && SHOW_CODENAME="y"
    [ -z "${SHOW_DESCR}" ] && SHOW_DESCR="y"
    [ -z "${SHOW_ID}" ] && SHOW_ID="y"
    [ -z "${SHOW_REL}" ] && SHOW_REL="y"
  fi

  GetLSBInfo
  GetDistribInfo

  # Выводим запрошенную информацию
  [ -n "${SHOW_ID}" ] && DisplayID
  [ -n "${SHOW_DESCR}" ] && DisplayDescription
  [ -n "${SHOW_REL}" ] && DisplayRelease
  [ -n "${SHOW_CODENAME}" ] && DisplayCodename

  echo -ne "${MSG_RESULT}"
  exit ${EXIT_STATUS}
}

# Запуск основной функции с переданными аргументами
main "$@"
