#!/usr/bin/python3
# Style Guide: https://www.python.org/dev/peps/pep-0008/

import argparse
import configparser
import pprint
import psycopg2

# fcntoolbox package
import fcntoolbox.dolibarr as dolibarr
import fcntoolbox.mail as mail
import fcntoolbox.sympa as sympa

# network imports
import smtplib
from email.mime.text import MIMEText

parser = argparse.ArgumentParser()

parser.add_argument("-c", "--config", type=str,
                    default="/etc/fcntoolbox/config.ini",
                    help="specify a configuration file")
args = parser.parse_args()

config = configparser.RawConfigParser()
config.sections()
config.read(args.config)
confac = config['ac']
confdoli = config['dolibarr']
confsympa = config['sympa']

conn = psycopg2.connect(host=confdoli['host'], database=confdoli['database'], 
  user=confdoli['user'], password=confdoli['password'])

doli = dolibarr.Instance(conn)

fields = ["rowid", "firstname", "lastname", "email"]
fieldsextra = ['email_second']

# Filter out missing extra fields
#cur.execute("SELECT * FROM llx_adherent_extrafields LIMIT 1")
#columns_extra = map(lambda col : col.name, cur.description)
#rows_extra = filter(lambda r : r in columns_extra, fieldsextra)

cur = doli.get_adherent(fields, fieldsextra)

aliases = mail.Aliases('/etc/aliases', 'franciliens.net')
raliases = dict((val, key) for key, val in aliases.items())

adherents = set() # set(email)
adherents_alt = dict() # dict(email => set(email))
radherents_alt = dict() # dict(email => email)
for record in cur:
  columns = map(lambda col : col.name, cur.description)
  adh = dict(zip(columns, record))
  adh_email = adh['email'].lower()
  adherents.add(adh_email)
  adh_alt = set()
  if 'email_second' in adh and adh['email_second'] != None:
    adh_alt.add(adh['email_second'])
    radherents_alt[adh['email_second']] = adh_email
  if adh_email in aliases:
    adh_alt.add(aliases[adh_email])
    radherents_alt[aliases[adh_email]] = adh_email
  if adh_email in raliases:
    adh_alt.add(raliases[adh_email])
    radherents_alt[raliases[adh_email]] = adh_email
  adherents_alt[adh_email] = adh_alt

sympaconn = psycopg2.connect(host=confsympa['host'], database=confsympa['database'], 
  user=confsympa['user'], password=confsympa['password'])
sympaIns = sympa.Instance(sympaconn)
list = 'adherents'
francisubs = set(sympaIns.get_subscribers(list, confsympa['robot']))

tosubscribe = set()
for adh in adherents:
  adh_alt = adherents_alt[adh]
  if adh in francisubs or len(adh_alt.intersection(francisubs)) > 0:
    pass
  else:
    tosubscribe.add(adh)

tounsubscribe = set()
for sub in francisubs:
  if sub in adherents \
      or (sub in radherents_alt and radherents_alt[sub] in adherents):
    pass
  else:
    tounsubscribe.add(sub)

editors = set(sympaIns.get_editors(list, confsympa['robot']))
remeditors = set()
for editor in editors:
  if editor in adherents \
      or (editor in radherents_alt and radherents_alt[editor] in adherents):
    pass
  else:
    remeditors.add(editor)

reportFormat = open('/etc/fcntoolbox/fcn-report.format', 'r').read()

s = smtplib.SMTP('localhost')

pp = pprint.PrettyPrinter()

def sendReport(listname, tosubscribe, tounsubscribe, removeeditors):
  body = reportFormat.format(
    list = listname,
    tosubscribe = pp.pformat(tosubscribe),
    removesubscribers = pp.pformat(tounsubscribe),
    removeeditors = pp.pformat(removeeditors))
  msg = MIMEText(body)
  msg['Subject'] = "Rapport de la liste [%s]" % listname
  msg['From'] = confsympa['mail_from']
  if 'mail_cc' in confsympa:
    msg['Cc'] = confsympa['mail_cc']
  msg['To'] = "%s-request@%s" % (listname, confsympa['robot'])
  s.send_message(msg)

if len(adherents) > 0 and (len(tosubscribe) > 0 or len(tounsubscribe) > 0) :
  sendReport(list, tosubscribe, tounsubscribe, remeditors)

molists = confac['members_only_lists'].split(',')
for list in molists:
  subs = set(sympaIns.get_subscribers(list, confsympa['robot']))

  tounsubscribe = set()
  for sub in subs:
    if sub in adherents \
        or (sub in radherents_alt and radherents_alt[sub] in adherents):
      pass
    else:
      tounsubscribe.add(sub)

  editors = set(sympaIns.get_editors(list, confsympa['robot']))
  remeditors = set()
  for editor in editors:
    if editor in adherents \
        or (editor in radherents_alt and radherents_alt[editor] in adherents):
      pass
    else:
      remeditors.add(editor)

  if len(adherents) > 0 and len(tounsubscribe) > 0 :
    sendReport(list, {}, tounsubscribe, remeditors)

s.quit()