#!/usr/bin/env python2
# vim: expandtab:tabstop=4:shiftwidth=4

import argparse
import traceback
import sys
import os
import re
import ConfigParser

from openshift_ansible import awsutil

CONFIG_MAIN_SECTION = 'main'

class Ossh(object):
    def __init__(self):
        self.user = None
        self.host = None
        self.file_path = os.path.join(os.path.dirname(os.path.realpath(__file__)))

        # Default the config path to /etc
        self.config_path = os.path.join(os.path.sep, 'etc',  \
                                        'openshift_ansible', \
                                        'openshift_ansible.conf')

        self.parse_cli_args()
        self.parse_config_file()

        self.aws = awsutil.AwsUtil()

        if self.args.refresh_cache:
            self.get_hosts(True)
        else:
            self.get_hosts()

        # parse host and user
        self.process_host()

        if self.args.host == '' and not self.args.list:
            self.parser.print_help()
            return

        if self.args.debug:
            print self.args

        # perform the SSH
        if self.args.list:
            self.list_hosts()
        else:
            self.ssh()

    def parse_config_file(self):
        if os.path.isfile(self.config_path):
            config = ConfigParser.ConfigParser()
            config.read(self.config_path)

    def parse_cli_args(self):
        parser = argparse.ArgumentParser(description='OpenShift Online SSH Tool.')
        parser.add_argument('-d', '--debug', default=False,
                            action="store_true", help="debug mode")
        parser.add_argument('-v', '--verbose', default=False,
                            action="store_true", help="Verbose?")
        parser.add_argument('--refresh-cache', default=False,
                            action="store_true", help="Force a refresh on the host cache.")
        parser.add_argument('--list', default=False,
                            action="store_true", help="list out hosts")
        parser.add_argument('-c', '--command', action='store',
                            help='Command to run on remote host')
        parser.add_argument('-l', '--login_name', action='store',
                            help='User in which to ssh as')

        parser.add_argument('-o', '--ssh_opts', action='store',
                            help='options to pass to SSH.\n \
                                  "-oForwardX11=yes,TCPKeepAlive=yes"')
        parser.add_argument('-A', default=False, action="store_true",
                            help='Forward authentication agent')
        parser.add_argument('host', nargs='?', default='')

        self.args = parser.parse_args()
        self.parser = parser


    def process_host(self):
        '''Determine host name and user name for SSH.
        '''

        parts = self.args.host.split('@')

        # parse username if passed
        if len(parts) > 1:
            self.user = parts[0]
            self.host = parts[1]
        else:
            self.host = parts[0]

            if self.args.login_name:
                self.user = self.args.login_name


    def get_hosts(self, refresh_cache=False):
        '''Query our host inventory and return a dict where the format '''
        if refresh_cache:
            self.host_inventory = self.aws.get_inventory(['--refresh-cache'])['_meta']['hostvars']
        else:
            self.host_inventory = self.aws.get_inventory()['_meta']['hostvars']

    def select_host(self):
        '''select host attempts to match the host specified
           on the command line with a list of hosts.
        '''
        results = None
        if self.host_inventory.has_key(self.host):
           results = (self.host, self.host_inventory[self.host])
        else:
            print "Could not find specified host: %s." % self.host

        # default - no results found.
        return results

    def list_hosts(self, limit=None):
        '''Function to print out the host inventory.

           Takes a single parameter to limit the number of hosts printed.
        '''
        for host_id, server_info in self.host_inventory.items():
            print '{oo_name:<35} {oo_clusterid:<10} {oo_environment:<8} ' \
                '{oo_id:<15} {oo_public_ip:<18} {oo_private_ip:<18}'.format(**server_info)

    def ssh(self):
        '''SSH to a specified host
        '''
        try:
            # shell args start with the program name in position 1
            ssh_args = ['/usr/bin/ssh']

            if self.user:
                ssh_args.append('-l%s' % self.user)

            if self.args.A:
                ssh_args.append('-A')

            if self.args.verbose:
                ssh_args.append('-vvv')

            if self.args.ssh_opts:
                for arg in self.args.ssh_opts.split(","):
                    ssh_args.append("-o%s" % arg)

            results = self.select_host()
            if not results:
                return # early exit, no results

            # Assume we have one and only one.
            server_info = results[1]

            ssh_args.append(server_info['oo_public_ip'])

            #last argument
            if self.args.command:
                ssh_args.append("%s" % self.args.command)

            print "Running: %s\n" % ' '.join(ssh_args)

            os.execve('/usr/bin/ssh', ssh_args, os.environ)
        except:
            print traceback.print_exc()
            print sys.exc_info()


if __name__ == '__main__':
    ossh = Ossh()