#!/usr/bin/env python
from __future__ import with_statement

import datetime
import optparse
import os
import pwd
import re
import readline
import subprocess
import sys

from email.mime.text import MIMEText

BASEDIR = os.path.dirname(__file__)
REQUIRED_LISTS = [{'name' : 'sipb-prospectives-%i' % datetime.datetime.now().year,
                   'description' : 'List of all SIPB prospectives'}]
OPTIONAL_LISTS = [{'name' : 'rt-sipb-consultants',
                   'description' : 'Support list for random user questions.'},
                  {'name' : 'sipb-minutes',
                   'description' : 'Where the minutes taken at each meeting get sent'},
                  {'name' : 'sipb-soc',
                   'description' : 'The SIPB social list'},
                  {'name' : 'sipb-jobs',
                   'description' : 'Where people who are looking to hire you look'}]
OPTS = None
WELCOME_EMAIL = {'To' : '%(email)s',
                 'From' : 'The SIPB Chair <sipb-chair@mit.edu>',
                 'Bcc' : 'prospectivizations@mit.edu',
                 'Subject' : 'Welcome to SIPB!',
                 '__body__' :
"""So you've just become a SIPB prospective.  Welcome to the SIPB 
community, %(username)s!  We're excited that you've become interested in 
SIPB, and hope that you'll continue to hang out in our office and 
contribute to our projects.  Also, yes, this is an automated email, but 
that's not the point.

As I'm sure you know by now, there's a lot going on at SIPB!  This email 
is intended to give you pointers on how to get started on getting 
involved in the SIPB community.  If you have any questions, don't 
hesitate to hit that reply button.

== Useful Documents ==

/afs/sipb/admin/text/members/how-to-become-a-member.txt: Wondering how to 
become a full fledged SIPB member?  Look no further---this is the 
official guide to doing so.
/afs/sipb/admin/text/members/spiel.txt: Gives a broad overview of what SIPB 
does.  (%(prospectivizer)s likely was referring to this document when 
prospectivizing you.)

In general, /afs/sipb/admin/ has a lot of interesting material (old 
minutes, policies, etc.) that's worth poking at next time you are 
putting off a problem set.

== Community ==

SIPB is both a technical and a social organization.  A great deal of 
interaction occurs in the SIPB office (yes, even outside of meeting 
times).  Also, people tend to be on Zephyr more than is strictly 
healthy for them.  (See http://sipb.mit.edu/doc/zephyr/ if you are not 
familiar with zephyr.)

== Useful Websites ==

sipb.mit.edu - The SIPB website.
scripts.mit.edu - Scripts is a web-hosting service we run; use common web apps or write your own.
xvm.mit.edu - XVM is a virtual machine service, great for running your own server.
debathena.mit.edu - Download a version of Debathena suitable for your personal computer.
mirrors.mit.edu - offers on-campus mirrors for a number of Linux distros and other FOSS projects.
"""}

class Error(Exception):
    pass

def run(*args):
    if OPTS.dryrun:
        print 'Would have run %s' % str(args)
    else:
        print 'Running:', args
        p = subprocess.Popen(args)
        p.communicate()
        if p.returncode:
            print 'Command returned %d' % p.returncode
            # raise Error()

def prompt(msg, default=True):
    if default:
        append = '[Yn]'
    else:
        append = '[yN]'
    input = raw_input('%s %s ' % (msg, append)).strip()
    if default:
        return not input.startswith('n')
    else:
        return input.startswith('y')

def normalize(relpath):
    return os.path.join(BASEDIR, relpath)

def add_to_list(list, username):
    if '@' in username:
        username = 'string:%s' % username
    print 'Adding %s to %s@ (%s)' % (username, list['name'], list['description'])
    run('blanche', '-a', username, list['name'])

def main():
    global OPTS

    parser = optparse.OptionParser(usage='usage: %prog [options] username')
    parser.add_option('-m', '--me', dest='me', help='Your username')
    parser.add_option('-n', '--dry-run', dest='dryrun',
                      action='store_true', default=False,
                      help='Just show what would happen')
    parser.add_option('-d', '--dont-email', dest='email', default=True,
                      action='store_false', help="Don't send a welcome email")
    parser.add_option('-l', '--dont-add-to-list', dest='list', default=True,
                      action='store_false',
                      help="Don't add to list of prospectives")
    parser.add_option('-b', '--dont-blanche', dest='blanche', default=True,
                      action='store_false',
                      help="Don't blanche onto lists")
    (opts, args) = parser.parse_args()
    OPTS = opts

    if len(args) != 1:
        parser.print_help()
        return 1
    else:
        prospective = args[0]

    me = opts.me or os.getenv('ATHENA_USER') or pwd.getpwuid(os.getuid()).pw_name

    if opts.list:
        print 'Checking out the members_and_prospectives document'
        members_and_prospectives = normalize('members_and_prospectives')
        run('co', '-l', members_and_prospectives)

        with open(members_and_prospectives) as f:
            current_text = f.readlines()

        new_text = []
        for line in current_text:
            if line.startswith('####### Others'):
                date = datetime.datetime.now().strftime('%Y-%m-%d')
                newline = ('%-14s  prospective     %-22s  %s\n' %
                           (prospective, me, date))
                if opts.dryrun:
                    print 'Would have added line "%s"' % newline.strip()
                else:
                    print 'Adding line "%s"' % newline.strip()
                new_text.append(newline)
            new_text.append(line)

        if not opts.dryrun:
            with open(members_and_prospectives, 'w') as f:
                f.writelines(new_text)

        run('ci', '-u', '-mAdded %s to the list of prospectives' % prospective, members_and_prospectives)

    if opts.blanche:
        for list in REQUIRED_LISTS:
            add_to_list(list, prospective)

        for list in OPTIONAL_LISTS:
            if not prompt('Should we add to %s@ (%s)' %
                          (list['name'], list['description'])):
                continue
            add_to_list(list, prospective)

    if opts.email:
        if '@' not in prospective:
            email = '%s@mit.edu' % prospective
        else:
            email = prospective
        username = email.split('@')[0]
        env = {'email' : email,
               'username' : username,
               'prospectivizer' : me}
        msg = MIMEText(WELCOME_EMAIL['__body__'] % env)
        msg.set_param('format', 'flowed')
        for k, v in WELCOME_EMAIL.iteritems():
            if k in ['__body__', 'Bcc']:
                continue
            msg[k] = v % env
        if opts.dryrun:
            print 'Would have sent welcome email to %s' % email
            print msg.as_string()
        else:
            print 'Sending welcome email to %s' % email
            p = subprocess.Popen(['/usr/lib/sendmail', email, WELCOME_EMAIL['Bcc']], stdin=subprocess.PIPE)
            p.communicate(input=msg.as_string())
            p.wait()
            if p.returncode:
                print 'Command returned %d' % p.returncode
    print 'All done!'

if __name__ == '__main__':
    sys.exit(main())
