#!/usr/bin/env python

import argparse
from isign import isign
from os.path import abspath, expanduser
import logging

FORMATTER = logging.Formatter('%(message)s')


def log_to_stderr(level=logging.INFO):
    root = logging.getLogger()
    root.setLevel(level)
    handler = logging.StreamHandler()
    handler.setFormatter(FORMATTER)
    root.addHandler(handler)


def absolute_path_argument(path):
    return abspath(expanduser(path))


def parse_args():
    # note that for arguments which eventually get fed into
    # isign.resign, we deliberately don't set defaults. The kwarg
    # defaults in isign.resign will be used
    parser = argparse.ArgumentParser(
        description='Resign an iOS application with a new identity '
                    'and provisioning profile.')
    parser.add_argument(
        '-p', '--provisioning-profile',
        dest='provisioning_profile',
        required=False,
        metavar='<your.mobileprovision path>',
        type=absolute_path_argument,
        help='Path to provisioning profile'
    )
    parser.add_argument(
        '-a', '--apple-cert',
        dest='apple_cert',
        required=False,
        metavar='<apple cert>',
        type=absolute_path_argument,
        help='Path to Apple certificate in .pem form'
    )
    parser.add_argument(
        '-k', '--key',
        dest='key',
        required=False,
        metavar='<key path>',
        type=absolute_path_argument,
        help='Path to your organization\'s key in .p12 format'
    )
    parser.add_argument(
        '-c', '--certificate',
        dest='certificate',
        required=False,
        metavar='<certificate path>',
        type=absolute_path_argument,
        help='Path to your organization\'s certificate in .pem form'
    )
    parser.add_argument(
        '-o', '--output',
        dest='output_path',
        required=False,
        metavar='<output path>',
        type=absolute_path_argument,
        help='Path to output file or directory'
    )
    parser.add_argument(
        'app_paths',
        nargs=1,
        metavar='<app path>',
        type=absolute_path_argument,
        help='Path to application to re-sign, typically a '
             'directory ending in .app or file ending in .ipa.'
    )
    parser.add_argument(
        '-v', '--verbose',
        dest='verbose',
        action='store_true',
        default=False,
        required=False,
        help='Set logging level to debug.'
    )
    parser.add_argument(
        '-i', '--info',
        dest='info_props',
        required=False,
        metavar='<Info.plist properties>',
        help='List of comma-delimited key=value pairs of Info.plist properties to override'
    )
    parser.add_argument(
        '-d', '--display',
        dest='display_only',
        action='store_true',
        default=False,
        required=False,
        help='Display information about the app without resigning'
    )
    return parser.parse_args()

if __name__ == '__main__':
    args = parse_args()

    if args.verbose:
        level = logging.DEBUG
    else:
        level = logging.INFO
    log_to_stderr(level)

    if args.display_only:
        import json
        bundle_info = isign.view(args.app_paths[0])
        print json.dumps(bundle_info, indent=4, separators=(',', ': '))
    else:
        # Filter out args that don't matter to the
        # resign call, like verbosity or help
        resign_args = ['certificate',
                       'key',
                       'apple_cert',
                       'provisioning_profile',
                       'output_path']
        kwargs = {}
        # we want the unused command line args to be
        # missing in kwargs, so the defaults are used
        for k, v in vars(args).iteritems():
            if k in resign_args and v is not None:
                kwargs[k] = v

        # Convert the Info.plist property pairs to a dict format
        if args.info_props:
            info_props = {}
            for arg in args.info_props.split(','):
                i = arg.find('=')
                if i < 0:
                    raise Exception('Invalid Info.plist argument: ' + arg)
                info_props[arg[0:i]] = arg[i + 1:]
            if info_props:
                kwargs['info_props'] = info_props

        isign.resign(args.app_paths[0], **kwargs)
