#! /usr/bin/python2.7
#-----------------------------------------------------------------------
# File:        fns-find-icon
__version__ = '1.3.6'
# Licence:     GPL 2
#
# Description: get the iconpath of an application or icon
# Parameters:  -n <name>        Name of the application/icon
#              -i <id>          Window id of the application
#              -p <path(s)>     More search path(s). Seperated with ':'
#              -s <size>        Source icon size. Default is 48
#              -c <category>    Default is 'apps'
#              -t <theme>       Other used theme or 'all'. Default is None
#              --notdesk        Don't search in desktop files. Default is false
#              --version        Prints version
#              --svg            Prefer svg and if found add ':<size>x<size>' to the path.
#
# Author:      Thomas Funk <t.funk@web.de>
# Created:     09/22/2012
# Changed:     06/04/2016
#-----------------------------------------------------------------------

import os, sys, time
import subprocess
import fnmatch
import argparse

def print_(s):
    sys.stdout.write(str(s))
    
def search_file(filename, searchpaths, nodesktop=False, svgwanted=False, pathsep=os.pathsep):
    """ Given a search path, find file with requested name """
    png_remember = ''
    for path in searchpaths.split(pathsep):
        if os.path.exists(path):
            file_list = os.listdir(path)
            if nodesktop:
                pattern = filename+'.*'
            else:
                pattern = '*'+filename+'*'
            filenames = fnmatch.filter(file_list, pattern)
            if len(filenames) == 0:
                continue
            else:
                if svgwanted:
                    name = ''
                    for svg_filename in filenames:
                        if os.path.splitext(svg_filename)[1][1:].strip().lower() == 'svg':
                            return os.path.join(path, svg_filename)
                    if png_remember == '':
                        png_remember = os.path.join(path, filenames[0])
                else:
                    return os.path.join(path, filenames[0])
    if not png_remember == '':
        return png_remember
    return ''

def get_default_theme():
    out = ''
    desktop_config = os.path.join(os.environ['FVWM_USERDIR'], '.FvwmForm-Desktop-Config')
    if os.path.isfile(desktop_config):
        cmd = "awk '$2 ~ \"Theme\" { print $3 }' "+desktop_config
        out = subprocess.check_output([cmd], shell=True, universal_newlines=True).replace('\n', '')
    else:
        desktop_config = os.path.join(os.environ['FVWM_USERDIR'], '.fns-menu.cfg')
        if os.path.isfile(desktop_config):
            cmd = "awk '$1 ~ \"IconTheme\" { gsub(\"[:'\"'\"']\",\"\"); print $3 }' "+desktop_config
            out = os.path.basename(subprocess.check_output([cmd], shell=True, universal_newlines=True).replace('\n', ''))
    if out == '':
        return ['gnome']
    else:
        return [out]

def get_menu_icon_path(app_name):
    menu_path = os.path.join(os.environ['FVWM_USERDIR'], '.menu')
    cmd = "grep -m1 "+app_name+" "+menu_path+" |cut -d'%' -f2"
    icon_path = subprocess.check_output([cmd], shell=True, universal_newlines=True).replace('\n', '')
    return icon_path
    
def get_dektop_icon_path(app_name):
    search_paths = '/usr/share/applications' + os.pathsep \
                    + os.path.join(os.environ['HOME'], '.local/share/applications')
    desktop_file_path = search_file(app_name, search_paths)
    
    if desktop_file_path:
        cmd = "grep '[Ii]con' "+desktop_file_path
        icon_path = subprocess.check_output([cmd], shell=True, universal_newlines=True).replace('\n', '')
        icon_path = icon_path.replace(' ', '').split('=')[1]
        return icon_path
    else:
        return ''

def check_convert(iconpath, iconsize, svg_prefered):
    if os.path.splitext(iconpath)[1] == '.svg' and not svg_prefered \
    or not os.path.splitext(iconpath)[1] == '.svg' and not iconsize in iconpath:
        basename = os.path.basename(iconpath)
        # check that $FVWM_USERDIR/temp exist
        fns_temp_dir = os.path.join(os.environ['FVWM_USERDIR'],'temp')
        if not os.path.exists(fns_temp_dir):
			os.makedirs(fns_temp_dir)
        new_iconpath = os.path.join(fns_temp_dir, basename.replace('.svg', '.png'))
        # convert icon to needed size
        os.system('convert '+iconpath+' -resize '+iconsize+' '+new_iconpath)
        return new_iconpath
    else:
        if svg_prefered and os.path.splitext(iconpath)[1] == '.svg':
            iconpath = iconpath+":"+iconsize
        return iconpath
    
    
if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='get the iconpath of an application or icon')
    parser.add_argument('--version', action='version', version="%(prog)s V " + __version__)
    parser.add_argument('-n', action="store", dest="name", help='name of the application')
    parser.add_argument('-i', action="store", dest="w_id", help='window id of the application')
    parser.add_argument('-p', action="store", dest="extend_path", help='more search path(s). Seperated with \':\'')
    parser.add_argument('-s', action="store", dest="icon_size", help='source icon size. Default is 48', default='48')
    parser.add_argument('-c', action="store", dest="category", help='category. Default is apps', default='apps')
    parser.add_argument('-t', action="store", dest="theme", help='other theme. Default is None', default=None)
    parser.add_argument('--notdesk', action="store_true", dest="not_desktop_file", help='Don\'t search in desktop files. Default is false', default=False)
    parser.add_argument('--svg', action="store_true", dest="prefer_svg", help='Prefer svg and if found add \':<size>x<size>\' to the path. Default is false', default=False)

    args = parser.parse_args()
    
    app_name = args.name
    window_id = args.w_id
    extend_path = args.extend_path
    icon_size = args.icon_size
    category = args.category
    other_theme = args.theme
    not_desktop_file = args.not_desktop_file
    prefer_svg = args.prefer_svg
    
    if app_name and window_id:
        sys.stderr.write("Use either '-n' or '-i'. Exiting.\n")
        sys.exit(1)
    
    ts = time.time()

    icon_system_dirs = '/usr/share/icons/'
    icon_local_dirs = os.path.join(os.environ['HOME'], '.icons/')
    if not other_theme == None:
        if other_theme == 'all':
            themes = []
            for theme_path in [icon_system_dirs, icon_local_dirs]:
                themes += os.listdir(theme_path)
        else:
            themes = [other_theme]
    else:
        # get the used theme in fvwm-menu-desktop-config / fns-menu-config
        themes = get_default_theme()
    
    #print theme(s)
    i_size = icon_size+'x'+icon_size
    search_path = ''
    for theme_path in [icon_local_dirs, icon_system_dirs]:
        for theme in themes:
            if prefer_svg:
                search_path += theme_path + theme + '/scalable/' + category + os.pathsep \
                            + theme_path + theme + '/' + category + '/scalable/' + os.pathsep \
                            + theme_path + theme + '/' + category + '/scalable/' + os.pathsep
            search_path += theme_path + theme + '/' + i_size + '/' + category + os.pathsep \
                        + theme_path + theme + '/' + category + '/' + i_size + os.pathsep \
                        + theme_path + theme + '/' + category + '/' + icon_size + os.pathsep
    if len(themes) == 1:
        if prefer_svg:
            search_path += os.pathsep + '/usr/share/icons/hicolor/scalable/'+category
        search_path += os.pathsep + '/usr/share/icons/hicolor/'+i_size+'/'+category + os.pathsep
    search_path += '/usr/share/pixmaps'

    # extend search path if given
    if extend_path:
        search_path = search_path + os.pathsep + extend_path
    
    # make app name lower if given
    if app_name:
        app_name = app_name.lower()
    
    # get app name if window id is given
    if window_id:
        cmd = "xprop -id "+window_id+" WM_CLASS |cut -d',' -f2 |cut -d'\"' -f2"
        app_name = subprocess.check_output([cmd], shell=True, universal_newlines=True).replace('\n', '')
        app_name = app_name.lower()
        # reduce it for better finding
        app_name = app_name.split('-')[0]
        app_name = app_name.split('.')[0]
    

    if not_desktop_file:
        # search only for icons
        icon_path = search_file(app_name, search_path, not_desktop_file, prefer_svg)
    else:
        # first find app's desktop file and get the icon path
        icon_path = get_dektop_icon_path(app_name)

    if os.path.isabs(icon_path):
        # if icon is a svg, convert it
        icon_path = check_convert(icon_path, i_size, prefer_svg)
        print_(icon_path)
    else:
        if icon_path == '':
            if len(themes) > 1:
                err_str = "[Fvwm-Nightshade][fns-find-icon]: No icon found in all themes named '"+app_name+"' with size "+i_size+" in category '"+category+"'\n"
            else:
                err_str = "[Fvwm-Nightshade][fns-find-icon]: No icon found in '"+''.join(themes)+"' theme named '"+app_name+"' with size "+i_size+" in category '"+category+"'\n"
            sys.stderr.write(err_str)
            sys.exit(1)
        else:
            if not not_desktop_file:
                # check, if icon path is found in the search paths
                icon_path = search_file(icon_path, search_path)
                if not os.path.isabs(icon_path):
                    # get icon path from .menu
                    icon_path = get_menu_icon_path(app_name)
                    if icon_path == '':
                        sys.stderr.write("[Fvwm-Nightshade][fns-find-icon]: No icon found for app named '"+app_name+"' with size "+i_size+" in category '"+category+"'\n")
                        sys.exit(1)
        print_(icon_path)
    #print "duration: " + str(time.time()-ts)
    sys.exit()
