#!/usr/bin/env python3

# (c) Copyright 2008 Vincent Bernat <bernat@debian.org>
# and licensed under GPL
# Inspired by scripts by Michael Stilkerich <ms@mike2k.de>

# Helper script to create menu from the output of
# /etc/menu-methods/fvwm-crystal

# Here is what we should have:

# text|*|/usr/bin/emacs22 -nw|*|Emacs 22 (text)|*|/debian/Applications/Editeurs|*|/usr/share/emacs/22.2/etc/images/icons/emacs_32.xpm
# x11|*|/usr/bin/emacs22|*|Emacs 22 (X11)|*|/debian/Applications/Editeurs|*|/usr/share/emacs/22.2/etc/images/icons/emacs_32.xpm

import os

FC_ICONBASE="/usr/share/fvwm-crystal/fvwm/icons/Default"
DM_ICONBASE="/var/lib/fvwm-crystal/icons/Default"
if os.getuid() == 0:
    DM_ICONBASE_W=DM_ICONBASE
else:
    DM_ICONBASE_W=os.path.expanduser("~/.fvwm/icons/Default")
SYSTEM_ICONDIRS = [ "/usr/share/pixmaps", "/usr/share/icons" ]
SIZES = [ "22x22", "32x32", "48x48" ]

import sys
import stat
import getopt
import subprocess

def trans(char):
    if char.isalnum():
        return char
    if char in ["-", "_", ".", "(", ")", ",", "+"]:
        return char
    return "_"
transtable = "".join([trans(chr(x)) for x in range(0, 256)])

def remove(base):
    for top in [base, DM_ICONBASE]:
        for root, dirs, files in os.walk(top, topdown=False):
            for name in files:
                os.remove(os.path.join(root, name))
            for name in dirs:
                os.rmdir(os.path.join(root, name))

def install(base):

    icons = {}
    noicons = []
    for l in open(os.path.join(base, "fvwm-crystal.debian-menu")).readlines():
        if l.startswith("#"):
            continue
        try:
            needs, command, title, section, icon = l.strip().split("|*|")
        except ValueError:
            continue

        # Translate dangerous characters
        title = title.translate(transtable)
        shortcommand = command.split(" ")[0].split("/")[-1].translate(transtable)

        # Create the file/directory
        filename = "%s%s/~%s~%s" % (base, section, shortcommand, title)
        if not os.path.isdir(os.path.dirname(filename)):
            os.makedirs(os.path.dirname(filename))
        target = open(filename, "w")
        target.write("""#!/bin/sh
# This file has been generated automatically by fvwm-crystal
# update-menus method. Do not edit it. Any change will be lost.
# If you are not happy with the content of this file, override
# it in one of those locations:
#  - %s
#  - %s
#
# You can either provide a new content or use a non executable
# file to discard it.

""" % (filename.replace("/var/lib/fvwm-crystal", "/usr/share/fvwm-crystal/fvwm"),
       filename.replace("/var/lib/fvwm-crystal", "~/.fvwm")))
        if needs == "text":
            # We try to escape a bit the command but we don't try to be overly complex
            target.write("exec FvwmCommand 'A %s $@'\n" % command.replace("'", "\'"))
        elif needs == "x11":
            # We use exec, this means that if the command is a shell
            # built-in, this won't work. We prefer to do that instead
            # of having a shell behind each command. Some shell are
            # intelligent enough to autoexec if needed but dash is
            # not.
            target.write("exec %s $@\n" % command)
        target.close()
        os.chmod(filename, stat.S_IRWXU | stat.S_IRGRP | stat.S_IROTH | stat.S_IXGRP | stat.S_IXOTH)

        # We need to take care of the icon now
        if shortcommand in noicons:
            # We have alread searched for an icon
            continue
        if os.path.isfile(os.path.join(FC_ICONBASE, SIZES[0], "apps", "%s.png" % shortcommand)) or \
                os.path.isfile(os.path.join(DM_ICONBASE, SIZES[0], "apps", "%s.png" % shortcommand)) or \
                os.path.isfile(os.path.join(DM_ICONBASE_W, SIZES[0], "apps", "%s.png" % shortcommand)):
            # Nothing to do, the icon exists
            continue
        if not os.path.isfile(icon):
            # No icon has been provided, we need to find one
            if not icons:
                # We build a dictionary with all icons (only done one time)
                for bd in SYSTEM_ICONDIRS:
                    for root, dirs, files in os.walk(bd):
                        for name in files:
                            if name.endswith(".png") or name.endswith(".xpm"):
                                m = name.lower()[:-4]
                                if m not in icons or name.endswith(".png"):
                                    icons[m] = os.path.join(root, name)
            if shortcommand.lower() in icons:
                icon = icons[shortcommand.lower()]
        if os.path.isfile(icon):
            # We have an icon, convert it
            for size in SIZES:
                if not os.path.isdir(os.path.join(DM_ICONBASE_W, size, "apps")):
                    os.makedirs(os.path.join(DM_ICONBASE_W, size, "apps"))
                subprocess.call(["convert", "-resize", size, icon,
                                 os.path.join(DM_ICONBASE_W, size, "apps", "%s.png" % shortcommand)])
        else:
            noicons.append(shortcommand)

    # Clean up
    os.unlink(os.path.join(base, "fvwm-crystal.debian-menu"))
            

def usage():
    print("%s [--install|--remove] base" % sys.argv[0], file=sys.stderr)

if __name__ == "__main__":
    try:
        opts, args = getopt.getopt(sys.argv[1:], 'hi:r:', ["help", "install=", "remove="])
    except getopt.GetoptError as err:
        print(str(err), file=sys.stderr)
        usage()
        sys.exit(2)
    if args:
        print("Don't know what to do with %s" % " ".join(args))
        usage()
        sys.exit(1)
    for o, a in opts:
        if o in ("-r", "--remove"):
            remove(a)
        elif o in ("-i", "--install"):
            install(a)
        else:
            usage()
            sys.exit(0)
