#!/usr/bin/python3
#
# Copyright (C) 2014 Canonical Ltd.
# Author: Michael Vogt <michael.vogt@ubuntu.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 3 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

from glob import glob
import os.path
import logging
import subprocess
import string


class Path:
    SRC_DIR = "/var/lib/systemd/click/"
    DEST_DIR = "/etc/systemd/system"
    SYSTEMCTL = "/bin/systemctl"

# FIXME: too simplisitic?
# i.e. should we avoid leaking this and record the state elsewhere?
CLICK_OWNED_PREFIX = "clickowned_"


def remove(f):
    logging.info("Remove: %s" % f)
    subprocess.call([Path.SYSTEMCTL, "stop", CLICK_OWNED_PREFIX+f])
    subprocess.call([Path.SYSTEMCTL, "disable", CLICK_OWNED_PREFIX + f])
    os.unlink(os.path.join(Path.DEST_DIR, CLICK_OWNED_PREFIX+f))


def install(f):
    logging.info("Install: %s" % f)
    update_content(f)
    subprocess.call([Path.SYSTEMCTL, "enable", CLICK_OWNED_PREFIX+f])
    subprocess.call([Path.SYSTEMCTL, "start", CLICK_OWNED_PREFIX+f])


def update_content(f):
    logging.info("Update content: %s" % f)
    f = os.path.join(Path.SRC_DIR, f)

    # FIXME: there is certainly a better way?
    app_triple = os.path.splitext(os.path.basename(f))[0]
    pkg, tmp, version = app_triple.split("_")
    manifest_path = os.path.join(".click", "info", "%s.manifest" % pkg)
    pkgpath = os.path.dirname(os.path.realpath(f))
    while not os.path.exists(os.path.join(pkgpath, manifest_path)):
        pkgpath = os.path.dirname(pkgpath)
        if pkgpath == "/":
            raise Exception("Can not find manifest for %s" % f)

    ext = os.path.splitext(os.path.realpath(f))[1]
    dst = os.path.join(
        Path.DEST_DIR, CLICK_OWNED_PREFIX + os.path.basename(f) + ext)
    with open(f) as f:
        content = f.read()
    with open(dst, "w") as f:
        template = string.Template(content)
        f.write(template.substitute({'CLICK_PACKAGE_PATH': pkgpath, }))


def update_systemd_units():
    srcdir = os.path.expanduser(Path.SRC_DIR)
    dstdir = os.path.expanduser(Path.DEST_DIR)

    old = set([os.path.basename(f)[len(CLICK_OWNED_PREFIX):]
               for f in glob(os.path.join(dstdir, CLICK_OWNED_PREFIX+"*"))])
    new = set([os.path.basename(f)
               for f in glob(os.path.join(srcdir, "*"))])
    for f in old - new:
        remove(f)
    for f in new - old:
        install(f)
    for f in new & old:
        if (os.path.getmtime(os.path.join(srcdir, f)) >
                os.path.getmtime(
                    os.path.join(dstdir, CLICK_OWNED_PREFIX + f))):
            update_content(f)


if __name__ == "__main__":
    update_systemd_units()
