#!/usr/bin/python

import os
import pwd
import re
import sys

import posixpath
import subprocess

from optparse import OptionParser


DEFAULT_DIRECTORY = "/var/cache/checkbox/qa-regression-testing"
DEFAULT_LOCATION = "http://bazaar.launchpad.net/%7Eubuntu-bugcontrol/qa-regression-testing/master"
DEFAULT_SUDO_PASSWORD = "insecure"

COMMAND_TEMPLATE = "cd %(scripts)s; python %(script)s"


def print_line(key, value):
    if type(value) is list:
        print "%s:" % key
        for v in value:
            print " %s" % v
    else:
        print "%s: %s" % (key, value)

def print_element(element):
    for key, value in element.iteritems():
        print_line(key, value)

    print

def fetch_qa_regression(location, directory):
    if posixpath.exists(directory):
        return

    process = subprocess.Popen(["bzr", "export", directory, location],
        stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    stdout, stderr = process.communicate()
    if process.returncode:
        raise Exception, "Failed to fetch from %s" % location

def list_qa_regression(location, directory, dry_run):
    if not dry_run:
        fetch_qa_regression(location, directory)

    script_pattern = re.compile(r"^test\-.*\.py$")

    directory = posixpath.join(directory, "scripts")
    for script in os.listdir(directory):
        if script_pattern.match(script):
            yield script

def run_qa_regression(scripts, location, directory, dry_run):
    if not dry_run:
        fetch_qa_regression(location, directory)

    for script in scripts:
        path = posixpath.join(directory, "scripts", script)

        # Initialize test structure
        test = {}
        test["plugin"] = "shell"
        test["name"] = posixpath.splitext(script)[0]
        test["command"] = COMMAND_TEMPLATE % {
            "scripts": posixpath.dirname(path),
            "script": posixpath.basename(path)}

        # Get description from first commented paragraph
        description = ""
        in_paragraph = True
        file = open(path)
        for line in file.readlines():
            if in_paragraph == True:
                if line.startswith("#") and not line.startswith("#!"):
                    in_paragraph = False

            elif in_paragraph == False:
                line = re.sub(r"#\s+", "", line).strip()
                if line:
                    test["description"] = line
                    break

        else:
            test["description"] = "No description found"

        # Get package requirements from QRT-Packages and QRT-Alternates
        pattern = re.compile(r"# (?P<key>[^ ]+): (?P<value>.*)$")
        packages = []
        file = open(path)
        for line in file.readlines():
            line = line.strip()
            match = pattern.match(line)
            # Check for match
            if not match:
                continue

            # Check for value with content
            value = match.group("value").strip()
            if not value:
                continue

            # Check for QRT-*
            values = re.split(r"\s+", value)
            if match.group("key") == "QRT-Packages":
                packages.extend(["package.name == '%s'" % v for v in values])

            elif match.group("key") == "QRT-Alternates":
                packages.append("%s" % " or ".join(["package.name == '%s'" % v for v in values]))

            elif match.group("key") == "QRT-Privilege":
                test["user"] = value

        if packages:
            test["requires"] = packages

        yield test

def main(args):
    usage = "Usage: %prog [OPTIONS] [SCRIPTS]"
    parser = OptionParser(usage=usage)
    parser.add_option("--dry-run",
        default=False,
        action="store_true",
        help="Dry run to avoid fetching from the given location.")
    parser.add_option("-d", "--directory",
        default=DEFAULT_DIRECTORY,
        help="Directory where to fetch qa-regression-testing")
    parser.add_option("-l", "--location",
        default=DEFAULT_LOCATION,
        help="Location from where to fetch qa-regression-testing")

    (options, scripts) = parser.parse_args(args)

    # Parse environment
    if os.getuid() != 0:
        parser.error("Must be run as root with sudo.")

    user = os.environ.get("SUDO_USER")
    if not user:
        parser.error("SUDO_USER variable not found, must be run with sudo.")

    dirname = posixpath.dirname(options.directory)
    if not posixpath.exists(dirname):
        os.makedirs(dirname)
        os.chmod(dirname, 0777)

    pw = pwd.getpwnam(user)
    os.setgid(pw.pw_gid)
    os.setuid(pw.pw_uid)
    os.chdir(pw.pw_dir)

    if not scripts:
        scripts = list_qa_regression(options.location, options.directory,
            options.dry_run)

    tests = run_qa_regression(scripts, options.location, options.directory,
        options.dry_run)
    if not tests:
        return 1

    for test in tests:
        print_element(test)

    return 0


if __name__ == "__main__":
    sys.exit(main(sys.argv[1:]))
