# ics.py
#
# Copyright 2020 Fabio
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import time
import html
from datetime import datetime, timedelta, timezone
from dateutil.tz import UTC
from icalendar import Calendar, Event

from .exceptions import InvalidFormatException
from .. import local
from ..models import Meta


def import_ics(content:str, url:str):
    """Import data from ICS

    all dates will be converted to UTC and stored in db without tzinfo,
    because sqlite3 driver spits errors otherwise.
    """

    cal = Calendar.from_ical(content)

    _db = local.getDb()

    meta_title = None
    meta_end = datetime(1970,1,1,0,0,0)
    meta_start = datetime(3100,12,12,23,59,59)

    for c in cal.walk():
        if c.name == "VCALENDAR":
            meta_title = c.get('X-WR-CALNAME')

        if c.name == "VEVENT":
            fulltextsearch = []
            eventid = c['UID']
            if c.get('DTSTART'):
                start = c['DTSTART'].dt.astimezone(UTC).replace(tzinfo=None)
            else:
                start = c['DTSTAMP'].dt.astimezone(UTC).replace(tzinfo=None)
            if c.get('DURATION'):
                end = start + c['DURATION'].dt
            elif c.get('DTEND'):
                end = c['DTEND'].dt.astimezone(UTC).replace(tzinfo=None)
            else:
                end = start + timedelta(hours=1)
            evtdate = start.date()
            room = c.get('LOCATION')
            slug = None
            title = c.get('SUMMARY', "")
            subtitle = None
            track = None
            evtype = None
            abstract = None
            description = c.get('DESCRIPTION', "")

            if title == "" and description == "":
                title = "Untitled event"
            if title == "" and description != "":
                title = description[:20]
                if len(description) > 20:
                    title = title + "…"

            if room:
                room = html.unescape(room)
            if room == "":
                room = None

            if start < meta_start:
                meta_start = start
            if end > meta_end:
                meta_end = end

            fulltextsearch += [ s for s in [title, subtitle, abstract, description, room, track] if s is not None ]

            links = []
            _url = c.get('URL')
            if _url:
                links.append((eventid, _url, _url))

            _db.execute("""INSERT OR REPLACE INTO events
                                (id, date, start, end, room, slug, title, subtitle, track, type, abstract, description, starred)
                                VALUES (?,?,?,?,?,?,?,?,?,?,?,?, (SELECT starred FROM events WHERE id=?))""",
                                (eventid, evtdate, start, end, room, slug, title, subtitle, track, evtype, abstract, description, eventid))
            #_db.executemany("INSERT OR REPLACE INTO persons (id, name) VALUES (?, ?)", persons)
            #_db.executemany("""INSERT OR REPLACE INTO event_person (event_id, person_id)
            #                    VALUES (?, ?) ON CONFLICT DO NOTHING""",
            #                    [ (eventid, p[0]) for p in persons ])
            _db.executemany("""INSERT OR REPLACE INTO links
                                (event_id, href, name) VALUES (?,?,?)""", links)
            fulltextsearchstr = ' '.join(fulltextsearch)
            _db.execute("""INSERT OR REPLACE INTO fts_event (event_id, text) VALUES (?, ?)""", (eventid, fulltextsearchstr))
    _db.commit()

    with Meta() as m:
        m.url = url
        m.title = meta_title
        m.last_update = time.time() # timestamp
        m.start = meta_start.date()
        m.end = meta_end.date()
