#!/usr/bin/env python

# Copyright 2014 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

import argparse
import json
import subprocess
import sys


def process_output(cmdline):
    # Try to execute subprocess.check_output(), which is available
    # in Python 2.7+, gracefully falling back to subprocess.Popen
    # in older Python versions.
    try:
        return subprocess.check_output(cmdline)
    except AttributeError:
        proc = subprocess.Popen(cmdline, stdout=subprocess.PIPE)
        out = proc.communicate()[0]
        if proc.returncode:
            e = subprocess.CalledProcessError(proc.returncode, cmdline)
            e.output = out
            raise e
        return out


def main():
    parser = argparse.ArgumentParser(
        description="Install or uninstall packages for a specific phase based"
                    " on package-installs files.")
    parser.add_argument('--phase', required=True,
                        help="Install phase to filter on. Valid options are"
                             " 'install.d' or pre-install.d")
    parser.add_argument('--uninstall', action="store_true",
                        help="Only show packages to uninstall. By default only"
                             " packages to install are shown")
    parser.add_argument('-n', '--noop', action="store_true",
                        help="Don't actually install, just print the command")
    parser.add_argument('infile', help="File to process")
    args = parser.parse_args()

    packages = json.load(open(args.infile))
    if args.uninstall:
        install = "uninstall"
    else:
        install = "install"

    pkgs = list()
    if args.phase in packages and install in packages[args.phase]:
        install_packages = packages[args.phase][install]
    else:
        print("Nothing to %s" % install)
        sys.exit(0)

    for (pkg, element) in install_packages:
        print("%sing %s from %s" % (install, pkg, element))
        pkg_map_args = ["pkg-map", "--missing-ok", "--element", element]
        pkg_map_args.append(pkg)

        try:
            map_output = process_output(
                pkg_map_args)
        except subprocess.CalledProcessError as e:
            if e.returncode == 1:
                if args.noop:
                    pkgs.append(pkg)
                    continue
                else:
                    print("pkg-map failed")
                    sys.exit(1)
            elif e.returncode == 2:
                pkgs.append(pkg)
                continue
        pkgs.extend(map_output.strip().split('\n'))

    install_args = ["install-packages"]
    if args.uninstall:
        install_args.append("-e")
    install_args.extend(list(set(pkgs)))

    if args.noop:
        print(" ".join(install_args))
    else:
        try:
            process_output(install_args)
        except subprocess.CalledProcessError as e:
            print("install failed with error %s" % e.output)
            sys.exit(1)


if __name__ == '__main__':
    main()
