#!/usr/bin/env python3

import argparse
import os
import tempfile
import shutil
import subprocess
import shlex

def run(command, verbose):
    if verbose:
        sys.stdout.write("$ {}\n".format(" ".join(
            shlex.quote(word) for word in command)))
    out = subprocess.check_output(command)
    if verbose:
        sys.stdout.write("".join(
            "> {}\n".format(line) for line in out.splitlines()))

def make_changes(msi, args):
    run(["msidump", "-t", msi], args.verbose)
    build_cmd = ["msibuild", msi]

    def change_table(filename):
        with open(filename) as fh:
            lines = [line.rstrip("\r\n").split("\t")
                     for line in iter(fh.readline, "")]

        for line in lines[3:]:
            yield line

        with open(filename, "w") as fh:
            for line in lines:
                fh.write("\t".join(line) + "\r\n")

        build_cmd.extend(["-i", filename])

    if args.platform is not None:
        for line in change_table("_SummaryInformation.idt"):
            if line[0] == "7":
                line[1] = ";".join([args.platform] + line[1].split(";", 1)[1:])

    if args.dialog_bmp_width is not None:
        for line in change_table("Control.idt"):
            if line[9] == "WixUI_Bmp_Dialog":
                line[5] = args.dialog_bmp_width

    run(build_cmd, args.verbose)

def main():
    parser = argparse.ArgumentParser(
        description='Change the platform field of an MSI installer package.')
    parser.add_argument("msi", help="MSI installer file.")
    parser.add_argument("--platform", help="Change the platform field.")
    parser.add_argument("--dialog-bmp-width", help="Change the width field"
                        " in all uses of WixUI_Bmp_Dialog.")
    parser.add_argument("-v", "--verbose", action="store_true",
                        help="Log what this script is doing.")
    parser.add_argument("-k", "--keep", action="store_true",
                        help="Don't delete the temporary working directory.")
    args = parser.parse_args()

    msi = os.path.abspath(args.msi)
    msidir = os.path.dirname(msi)
    try:
        tempdir = tempfile.mkdtemp(dir=msidir)
        os.chdir(tempdir)
        make_changes(msi, args)
    finally:
        if args.keep:
            sys.stdout.write(
                "Retained temporary directory {}\n".format(tempdir))
        else:
            shutil.rmtree(tempdir)

if __name__ == '__main__':
    main()
