#!/bin/bash

##########################################################
# Copyright (c) 2001-2025 Alexey Kuryakin daqgroup@mail.ru
##########################################################

##########################################################
# Utility to print MIME file associations by extension.
# References:
# 1) XDG Desktop Menu Specification.
# 2) XDG Base Directory Specification.
# 3) XDG Icon Theme Specification.
# 4) XDG Icon Naming Specification.
# 5) XDG Shared MIME-info Database.
# 6) XDG Desktop Entry Specification.
##########################################################

################################
# Current script identification.
################################
readonly startupdir="$(pwd -LP)";
readonly scriptfile="${BASH_SOURCE[0]}";
readonly scriptname="$(basename $scriptfile)";
readonly scriptbase="$(basename $scriptfile .sh)";
readonly scripthome="$(dirname  $scriptfile)";
readonly scriptFILE="$(realpath $scriptfile)";
readonly scriptHOME="$(dirname  $scriptFILE)";

source "$scriptHOME/ftype.in";

function do_version(){
 echo "$scriptname version 1.0";
};

function do_print_help(){
 do_version;
cat<<EOF
$scriptname Copyright (c) 2025 Alexey Kuryakin daqgroup@mail.ru
Utility to print MIME file associations by extension.
Usage:
 $scriptname [-options] [.ext [params]]
Options:
 --version  - print version
 -h,--help  - print help screen
 -d,--def   - print default handler name instead of MIME
 -e,--exec  - print Exec file full path  instead of MIME
 -i,--icon  - print Icon short name      instead of MIME
 -c,--cmd   - print command line with substituted params
Parameters:
 .ext       - file extension to print association
 params     - arguments for command line with option --cmd
Note:
 1) Default handler is default *.desktop file associated with extension
 2) Icon short name is base file name of picture from system stock
 3) With --cmd option 1st param (.ext) is file extension, next params
    is arguments for substitution (%f,%F,%u,%U) to replace. 
Examples:
 $scriptname            # print list of file extension associations
 $scriptname .txt       # print .txt extension associated MIME type
 $scriptname -d .txt    # print default handler associated with .txt
 $scriptname -i .txt    # print icon short name associated with .txt
 $scriptname -e .txt    # print executable file associated with .txt
 $scriptname -c .txt f  # print command line to open file (f) as text
 $scriptname --help     # print help screen
 $scriptname --version  # print version
EOF
};

function filter_globs(){
 grep -P    '^([a-zA-Z_][a-zA-Z_0-9/-]*):\*(\.[a-zA-Z_0-9][a-zA-Z_0-9-]+)\s*$' \
 | sed -E 's/^([a-zA-Z_][a-zA-Z_0-9/-]*):\*(\.[a-zA-Z_0-9][a-zA-Z_0-9-]+)\s*$/\2=\1/' \
 | sort -u;
};

function cat_assoc_globs(){
 local mime_globs="";
  local mime_globs2="";
 for dir in $(enum_mime_search_dirs); do
  mime_globs="$dir/globs";
  if [[ -e $mime_globs ]]; then
   cat $mime_globs | filter_globs;
   continue;
  fi;
  mime_globs2="$dir/globs2";
  if [[ -e $mime_globs2 ]]; then
   cat $mime_globs2 | sed -E 's/[0-9]+://' | filter_globs;
   continue;
  fi;
 done;
};

function assoc_globs(){
 cat_assoc_globs | sort -u;
};

function print_assoc(){
 if [[ -z $1 ]]; then
  assoc_globs;
  return;
 else
  while [[ -n $1 ]]; do
   if [[ "${1:0:1}" = "." ]]; then skip; else fatal 1 "Error: expected argument .* but found $1"; fi;
   if assoc_globs | grep -e "^$1="; then
    shift;
   else
    return;
   fi;
  done;
 fi; 
};

function cat_icons(){
 for pn in $(enum_mime_search_dirs); do
  for bn in generic-icons icons; do
   local fn="$pn/$bn";
   if [[ -e $fn ]]; then
    cat "$fn" | sort -u;
   fi;
  done;
 done;
};

function print_icons(){
 shift;
 while [[ -n $1 ]]; do
  local mime="$(print_assoc $1 | tail -n1 | cut -d'=' -f2)";
  if [[ -z $mime ]]; then return 1; fi;
  local icon="$(cat_icons | grep "$mime:" | sed 's/.*://')";
  if [[ -z $icon ]]; then icon="$($scriptHOME/ftype.sh -i "$mime" | drop_key_equal)"; fi;
  if [[ -n $icon ]]; then
   echo "$1=$icon";
   shift;
  else
   return 1;
  fi;
 done;
};

function print_execs(){
 if [[ "${1:0:2}" = "-c" ]]; then let opt_cmd=1; fi;
 shift;
 while [[ -n $1 ]]; do
  local mime="$(print_assoc $1 | tail -n1 | cut -d'=' -f2)";
  if [[ -z $mime ]]; then return 1; fi;
  local exec="$($scriptHOME/ftype.sh -e "$mime" | drop_key_equal)";
  if [[ -n $exec ]]; then
   if [[ $opt_cmd -eq 0 ]]; then
    echo "$1=$exec";
    shift;
   else
    echo -n "$1=";
    shift;
    subst_exec_args "$exec" "$@";
    return;
   fi;
  else
   return 1;
  fi;
 done;
};

function print_defhs(){
 shift;
 while [[ -n $1 ]]; do
  local mime="$(print_assoc $1 | tail -n1 | cut -d'=' -f2)";
  if [[ -z $mime ]]; then return 1; fi;
  local desk="$(sys_def_app "$mime")";
  if [[ -n $desk ]]; then
   echo "$1=$desk";
   shift;
  else
   return 1;
  fi;
 done;
};

######
# MAIN
######

function main(){
 case $1 in
  '')                print_assoc; ;;
  --version)         do_version; return 0; ;;
  -h|-help|--help)   do_print_help; return 0; ;;
  -i|-icon|--icon)   print_icons "$@"; ;;
  -e|-exec|--exec)   print_execs "$@"; ;;
  -c|-cmd|-cmd)      print_execs "$@"; ;;
  -d|-def|--def)     print_defhs "$@"; ;;
  -*)                fatal 1 "Error: bad option $1"; ;;
  *)                 print_assoc "$@"; ;;
 esac;
};

main "$@";

##############
## END OF FILE
##############
