#!/usr/bin/python3

import requests
from requests.auth import HTTPBasicAuth
import re
import xml.etree.ElementTree as ET


class Vevent:
    UID_REGEXP = re.compile('^UID:.*')
    SUMMARY_REGEXP = re.compile('^SUMMARY:.*')

    def __init__(self, lines):
        self._lines = lines
        self._uid = self._get_line_from_regexp(self.UID_REGEXP)
        self._summary = self._get_line_from_regexp(self.SUMMARY_REGEXP)

    def _get_line_from_regexp(self, regexp):
        for line in self._lines:
            if regexp.match(line):
                index = self._lines.index(line)
                return line + self._lines[index + 1]

    def get_vevent_for_put(self):
        return '\r\n'.join(self._lines)

    def get_as_vcal_for_put(self):
        str_vevent = 'BEGIN:VCALENDAR\r\n' + self.get_vevent_for_put() \
                     + '\r\nEND:VCALENDAR'
        # If you experience problem with the line below, try
        # return strvevent
        # instead
        return str_vevent.encode('utf-8')

    @property
    def uid(self):
        return self._uid

    @property
    def summary(self):
        return self._summary

    def __repr__(self):
        return '{}\n{}'.format(self._uid, self._summary)


def get_login():
    owncloud_omis_url = ''
    login = ''
    password = ''
    with open('/home/jenselme/.owncloud') as owncloud:
        owncloud_omis_url, login, password = [line for line in
                                              owncloud.read().split('\n') if line]
    return owncloud_omis_url, login, password

def fetch_all_vevents(urls, filter_dict):
    vevents = []
    for name, url in urls.items():
        current_vevents = get_vevents(url)
        if name in filter_dict:
            current_vevents = [vevent for vevent in current_vevents
                               if filter_dict[name].match(vevent.summary)]
        vevents.extend(current_vevents)
    return vevents

def get_vevents(get_url):
    calendar = requests.get(get_url).content.decode('utf-8')
    calendar_lines = [line for line in calendar.split('\r\n') if line]
    # Remove VCALENDAR lines
    del calendar_lines[0]
    del calendar_lines[-1]

    vevent_lines = []
    vevents = []
    for line in calendar_lines:
        vevent_lines.append(line)
        if VEVENT_END.match(line) and vevent_lines:
            vevents.append(Vevent(vevent_lines))
            vevent_lines = []
    return vevents

def delete_all_removed_vevents(fetch_vevents, destination_url, request_params):
    destination_uids = get_destination_calendar_uids(destination_url, request_params)
    source_uids = [vevent.uid for vevent in fetch_vevents]
    removed_from_source_uids = [uid for uid in destination_uids if uid not in source_uids]
    delete_all(removed_from_source_uids, destination_url, request_params)

def get_destination_calendar_uids(destination_url, request_params):
    resp = requests.request('PROPFIND', destination_url, **request_params)
    xml_str = resp.content.decode('utf-8')
    root = ET.fromstring(xml_str)
    hrefs_uid = []
    for response in root:
        for child in response:
            if child.tag == '{DAV:}href':
                hrefs_uid.append(child.text)
    uids = []
    for href in hrefs_uid:
        uid = href.split('/')[-1]
        if uid:
            uids.append(uid)
    return uids

def delete_all(uids, url, request_params):
    for uid in uids:
        delete_url = '{}/{}'.format(url, uid)
        requests.delete(delete_url, **request_params)

def put_all_vevents_as_vcalendars(vevents, calendar_put_url, request_params):
    for vevent in vevents:
        put_url = '{}/{}.ics'.format(calendar_put_url, vevent.uid)
        data = vevent.get_as_vcal_for_put()
        requests.put(put_url, data=data, **request_params)


if __name__ == '__main__':
    # Global variables
    VEVENT_END = re.compile('^END:VEVENT$')
    SOCIOLOGIE_ORGANISATION = re.compile('.*Sociologie des Organisations.*')
    EDT_FETCH_URLS = {'omis-org': 'https://ade6.centrale-marseille.fr/jsp/custom/modules/plannings/anonymous_cal.jsp?resources=804&projectId=15&calType=ical&firstDate=2015-01-06&lastDate=2015-06-30',
    'tc-electif': 'https://ade6.centrale-marseille.fr/jsp/custom/modules/plannings/anonymous_cal.jsp?resources=1043&projectId=15&calType=ical&firstDate=2014-11-24&lastDate=2015-04-30',
    'ENT': 'https://ade6.centrale-marseille.fr/jsp/custom/modules/plannings/anonymous_cal.jsp?resources=208&projectId=15&calType=ical&firstDate=2014-10-20&lastDate=2015-05-31',
    'omis-gB': 'https://ade6.centrale-marseille.fr/jsp/custom/modules/plannings/anonymous_cal.jsp?resources=507&projectId=15&calType=ical&firstDate=2014-09-15&lastDate=2015-05-31',
    'tc2-td3': 'https://ade6.centrale-marseille.fr/jsp/custom/modules/plannings/anonymous_cal.jsp?resources=194&projectId=15&calType=ical&firstDate=2014-09-01&lastDate=2015-06-30',
    'omis-i': 'https://ade6.centrale-marseille.fr/jsp/custom/modules/plannings/anonymous_cal.jsp?resources=814&projectId=15&calType=ical&firstDate=2014-09-01&lastDate=2015-05-31'}

    owncloud_omis_url, login, password = get_login()

    request_params = {'verify': False, 'auth': HTTPBasicAuth(login, password)}
    fetched_vevents = fetch_all_vevents(EDT_FETCH_URLS, {'omis-org': SOCIOLOGIE_ORGANISATION})
    delete_all_removed_vevents(fetched_vevents, owncloud_omis_url, request_params)
    put_all_vevents_as_vcalendars(fetched_vevents, owncloud_omis_url, request_params)
