#!/usr/bin/env python
# -*- coding: utf-8 -*-
# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
# Author: "Chris Ward" <cward@redhat.com>

# PY3 COMPAT
from __future__ import unicode_literals, absolute_import

# INTERNAL PYTHON MODULES
import argparse
from getpass import getuser
import logging
import pandas as pd

from members.utils import config, logr


# TODO #
# Do you need some cashing with max execution around 8 sec?


def _exclude(users, exclude):
    logr.debug('EXCLUDING USERS...')
    if isinstance(users, (pd.Series, list)):
        users = pd.DataFrame(index=users)

    assert isinstance(users, pd.DataFrame)

    exclude = exclude or []
    assert isinstance(exclude, list)

    if not exclude:
        logr.debug(' ... NO USERS TO EXCLUDE')
        return users

    k_before = len(users)
    users = users[~users.index.isin(exclude)]
    k_after = len(users)
    k_excluded = k_before - k_after
    logr.debug("{} members EXCLUDED".format(k_excluded))
    return users


def parse_cli():
    '''
    members "public" CLI API
    '''
    # Setup the argparser
    parser = argparse.ArgumentParser(
        description='Get list of members from various data sources')
    subparsers = parser.add_subparsers(help='Datasources', dest='src')

    parser.add_argument('-o', metavar='o', nargs='?',
                        dest='output', help='Output file')
    parser.add_argument('-v', '--verbose', action='store_true',
                        help="turn verbose logging ON")
    parser.add_argument('-d', '--debug', action='store_true',
                        help="turn debug logging ON")
    # FIXME SUPPORT excluding users from the final list before printing
    parser.add_argument('-x', '--exclude', metavar='USER', nargs='+',
                        help="exclude results users by pattern")
    parser.add_argument('-L', '--one-line', action='store_true',
                        help="return results on a single line")

    # Mailman 2
    mm2 = subparsers.add_parser('mailman2')
    mm2.add_argument('list_name', metavar='LIST_NAME',
                     help='Mailman 2 list name')
    mm2.add_argument('-B', '--base-url', metavar='BASE_URL',
                     help='URL to Mailman2 list-serve')
    # mm2.add_argument('-u', '--user', metavar='USER',
    #                 help='Username to login with')
    # mm2.add_argument('-p', '--password', metavar='PASS',
    #                 help='Password to login with')
    mm2.set_defaults(**dict((config.get('mailman2') or {}).items()))

    # Orgchart 3
    # SUPPORTS KERBEROS LOGIN ONLY FOR NOW
    oc3 = subparsers.add_parser('orgchart3')
    # FIXME: support by group
    oc3.add_argument('uid', metavar='NAME',
                     default=getuser(),
                     help='uid of team lead / manager')
    # oc3.add_argument('-f', '--filter', metavar='FILTER', choices=['location']
    #                 help='Orgchart3 member filters')
    oc3.add_argument('-B', '--base-url', metavar='URL',
                     help='URL to OrgChart3 server')
    oc3.add_argument('-UDED', '--use-default-email-domain', action='store_true',
                     help="don't append default email to usernames")
    oc3.add_argument('-DED', '--default-email-domain',
                     help="default email domain (eg: @example.com)")
    oc3.set_defaults(**dict((config.get('orgchart3') or {}).items()))

    # Github API - Github repo members
    g = subparsers.add_parser('github_repo')
    g.add_argument('repo_url',
                   help='Github "[user|group]/repo" resource uri')
    g.add_argument('target',
                   nargs='?',
                   choices=['assignees', 'collaborators', 'contributors',
                            'stargazers', 'teams', 'watchers'],
                   help='Github repository name')
    g.add_argument('user_attrs',
                   nargs=argparse.REMAINDER,
                   choices=['login', 'email', 'bio', 'company',
                            'created_at', 'hireable', 'location',
                            'updated_at', 'url'],
                   default='login',
                   help='Github User attribute (default: login)')
    g.add_argument('-t', '--token',
                   help='Github User Token (instead of password)')
    g.set_defaults(**dict((config.get('github_repo') or {}).items()))

    # Facebook API -
    # Facebook Group Members
    fb = subparsers.add_parser('facebook_group')
    fb.add_argument('group_id',
                    help='Facebook group id resource uri')
    fb.add_argument('-t', '--access_token',
                    help='Facebook Access Token (instead of password)')
    fb.add_argument('-f', '--fields',
                    nargs='*',
                    help='Facebook  Token (instead of password)')
    fb.set_defaults(**dict((config.get('facebook_group') or {}).items()))

    args = vars(parser.parse_args())  # parse and load args as a dict

    # Go ahead and deal with logging debug/verbosity setting
    if args['debug']:
        # logr = logging.getLogger()  # get root logger
        logr.setLevel(logging.DEBUG)
    elif args['verbose']:
        logr.setLevel(logging.INFO)
    else:
        logr.setLevel(logging.WARN)

    return args


if __name__ == "__main__":
    # Load the user config file from their home directory
    args = parse_cli()

    output_file = args['output']
    one_line = args['one_line']

    src = args['src']  # what data source are we targetting?

    # FIXME:  for p in plugins: p.extract()
    # add 'activated plugins' to config;
    if src == 'mailman2':
        # MAILMAN 2 list member extraction
        from members import mailman2
        list_name = args.get('list_name')
        base_url = args.get('base_url')

        lists = args.get('lists') or {}
        list_config = lists.get(list_name) or {}
        user = list_config.get('user')
        password = list_config.get('password')

        users = mailman2.extract(list_name=list_name, base_url=base_url,
                                 list_config=list_config, user=user,
                                 password=password)
    elif src == 'orgchart3':
        from members import orgchart3

        uid = args.get('uid', getuser())
        base_url = args.get('base_url')
        default_email_domain = args.get('default_email_domain')
        use_default_email_domain = args.get('use_default_email_domain')

        users = orgchart3.extract(
            uid=uid, base_url=base_url,
            use_default_email_domain=use_default_email_domain,
            default_email_domain=default_email_domain)
    elif src == 'github_repo':
        from members import github_repo

        user = args.get('user', getuser())
        password = args.get('password')
        token = args.get('token')
        user_attrs = args.get('user_attrs', ['login'])
        # DEFAULT to lookup assignees if target isn't set to avoid an error
        # assignees doesn't require authentication
        target = args.get('target', 'assignees')
        repo_url = args.get('repo_url')

        users = github_repo.extract(
            repo_url=repo_url, target=target, user=user, password=password,
            token=token, user_attrs=user_attrs)
    elif src == 'facebook_group':
        from members import facebook_group

        group_id = args.get('group_id')
        access_token = args.get('access_token')
        fields = args.get('fields') or []

        print group_id, access_token, fields, '*'*100
        users = facebook_group.extract(
            group_id=group_id, access_token=access_token, fields=fields)
        print users
    else:
        raise RuntimeError("Unknown datasource [{}]".format(src))

    if isinstance(users, dict):
        users = pd.DataFrame(users).T
        users.index.name = 'login'
    else:
        # otherwise we should expect a list of users
        assert isinstance(users, list)
        users = pd.Series(users)

    # remove users that match the exclude patterns
    users = _exclude(users, args['exclude'])

    # get name of the type of user attribute we're returning
    user_attrs = args.get('user_attrs') or []
    try:
        # SPECIAL CASE - Always get logins
        login_i = user_attrs.index('login')
        if login_i:
            # get this out of the remaining attrs to parse
            user_attrs.pop(login_i)
    except ValueError:
        # login isn't include, doesn't matter, we're running it anyway
        pass


    if one_line:
        output = ' '.join(users.index)
    else:
        output = users.to_csv()

    if output_file:
        with open(output_file, 'wb') as f:
            f.write(output)
    else:
        print(output)

    k_users = len(users)
    logr.info('{} found for {}'.format(k_users, src))
