#!/usr/bin/env python
import sys
import time
import logging
import argparse
import os.path

import github_watcher
import github_watcher.settings
import github_watcher.commands
import github_watcher.commands.run
import github_watcher.commands.check
import github_watcher.commands.config


THROTTLE_THRESHOLD = 600  # seconds
ACTION_HELP = '''
run|config - *run* Runs the daemon. Watches files and alerts when there is a pull request of interest.
             *config* Is a convenience tool to help you configure the watcher. You
              can add line ranges or directories, update the API url,
              or add new files to watch.
'''


def parse_cli():
    parser = argparse.ArgumentParser(description='')
    parser.add_argument('action', default='run', help=ACTION_HELP)
    parser.add_argument('--verbose', dest='verbose', action='store_true', default=False)
    parser.add_argument('--repo', dest='repo', default=None,
                        help='Used with "github-watcher check" to specify the repository to check. Required for check.')
    parser.add_argument('--user', dest='user', default=None,
                        help='Used with "github-watcher check" to specify the user who owns the repostory to check. ' +
                             'Required for check.')
    parser.add_argument('--filepath', dest='filepath', default=None,
                        help='Used with "github-watcher check" to specify the filepath to check. Required for check.')
    parser.add_argument('--start-lineno', dest='start', default=0,
                        help='Used with "github-watcher check" to specify the start of the line range to check. ' +
                             'Optional.')
    parser.add_argument('--end-lineno', dest='end', default=1000000,
                        help='Used with "github-watcher check" to speficy the end of the line range to check. ' +
                             'Optional.')
    parser.add_argument('--github-url', dest='github_url', default=None,
                        help='Supply a non-default github url where your enterprise installation can be found. It ' +
                             'should probably end with /api/v3. Defaults to the api.github.com API')
    parser.add_argument('--config', dest='config_file',
                        default=os.path.join(os.path.expanduser('~'), github_watcher.settings.WATCHER_CONFIG),
                        help='Specify a path to your github watcher config file.')
    parser.add_argument('--debug', dest='debug', default=False, action='store_true',
                        help="Pass this flag to include debug output. DANGER: This may print your access token.")
    return parser, parser.parse_args()


def daemonize(parser):
    backoff = 1
    while True:
        logging.info("Running `run` action...")
        try:
            last_invocation = time.time()
            github_watcher.commands.run.main(parser)
        except KeyboardInterrupt:
            sys.exit(0)
        except Exception as e:
            logging.exception(e)
            if time.time() - last_invocation > THROTTLE_THRESHOLD:
                logging.error('Backing off {} seconds'.format(backoff))
                backoff *= 2
            else:
                backoff = 1
            time.sleep(backoff)
            continue


def main():
    parser, args = parse_cli()
    if args.debug or args.verbose:
        logging.basicConfig(level=logging.INFO, format="%(levelname)s %(filename)s %(lineno)d: %(message)s")
    if args.action == 'run':
        daemonize(parser)
    elif args.action == 'config':
        github_watcher.commands.config.main(parser)
    elif args.action == 'check':
        github_watcher.commands.check.main(parser)
    else:
        parser.print_help()
        raise SystemExit


if __name__ == '__main__':
    main()
