__filename__ = "webapp_calendar.py"
__author__ = "Bob Mottram"
__license__ = "AGPL3+"
__version__ = "1.2.0"
__maintainer__ = "Bob Mottram"
__email__ = "bob@freedombone.net"
__status__ = "Production"
__module_group__ = "Calendar"
import os
from datetime import datetime
from datetime import date
from shutil import copyfile
from utils import getDisplayName
from utils import getConfigParam
from utils import getNicknameFromActor
from utils import getDomainFromActor
from utils import locatePost
from utils import loadJson
from utils import weekDayOfMonthStart
from utils import getAltPath
from utils import removeDomainPort
from utils import acctDir
from happening import getTodaysEvents
from happening import getCalendarEvents
from webapp_utils import htmlHeaderWithExternalStyle
from webapp_utils import htmlFooter
from webapp_utils import htmlHideFromScreenReader
from webapp_utils import htmlKeyboardNavigation
def htmlCalendarDeleteConfirm(cssCache: {}, translate: {}, baseDir: str,
                              path: str, httpPrefix: str,
                              domainFull: str, postId: str, postTime: str,
                              year: int, monthNumber: int,
                              dayNumber: int, callingDomain: str) -> str:
    """Shows a screen asking to confirm the deletion of a calendar event
    """
    nickname = getNicknameFromActor(path)
    actor = httpPrefix + '://' + domainFull + '/users/' + nickname
    domain, port = getDomainFromActor(actor)
    messageId = actor + '/statuses/' + postId
    postFilename = locatePost(baseDir, nickname, domain, messageId)
    if not postFilename:
        return None
    postJsonObject = loadJson(postFilename)
    if not postJsonObject:
        return None
    if os.path.isfile(baseDir + '/img/delete-background.png'):
        if not os.path.isfile(baseDir + '/accounts/delete-background.png'):
            copyfile(baseDir + '/img/delete-background.png',
                     baseDir + '/accounts/delete-background.png')
    deletePostStr = None
    cssFilename = baseDir + '/epicyon-profile.css'
    if os.path.isfile(baseDir + '/epicyon.css'):
        cssFilename = baseDir + '/epicyon.css'
    instanceTitle = \
        getConfigParam(baseDir, 'instanceTitle')
    deletePostStr = htmlHeaderWithExternalStyle(cssFilename, instanceTitle)
    deletePostStr += \
        '
' + postTime + ' ' + str(year) + '/' + \
        str(monthNumber) + \
        '/' + str(dayNumber) + '
'
    deletePostStr += ''
    deletePostStr += '  ' + \
        translate['Delete this event'] + '
'
    postActor = getAltPath(actor, domainFull, callingDomain)
    deletePostStr += \
        '  \n'
    deletePostStr += '\n'
    deletePostStr += htmlFooter()
    return deletePostStr
def _htmlCalendarDay(personCache: {}, cssCache: {}, translate: {},
                     baseDir: str, path: str,
                     year: int, monthNumber: int, dayNumber: int,
                     nickname: str, domain: str, dayEvents: [],
                     monthName: str, actor: str) -> str:
    """Show a day within the calendar
    """
    accountDir = acctDir(baseDir, nickname, domain)
    calendarFile = accountDir + '/.newCalendar'
    if os.path.isfile(calendarFile):
        os.remove(calendarFile)
    cssFilename = baseDir + '/epicyon-calendar.css'
    if os.path.isfile(baseDir + '/calendar.css'):
        cssFilename = baseDir + '/calendar.css'
    calActor = actor
    if '/users/' in actor:
        calActor = '/users/' + actor.split('/users/')[1]
    instanceTitle = getConfigParam(baseDir, 'instanceTitle')
    calendarStr = htmlHeaderWithExternalStyle(cssFilename, instanceTitle)
    calendarStr += '\n'
    calendarStr += '\n'
    calendarStr += \
        '  \n'
    calendarStr += \
        '  ' + str(dayNumber) + ' ' + monthName + \
        '
' + str(year) + '\n'
    calendarStr += '\n'
    calendarStr += '\n'
    if dayEvents:
        for eventPost in dayEvents:
            eventTime = None
            eventDescription = None
            eventPlace = None
            postId = None
            senderName = ''
            senderActor = None
            eventIsPublic = False
            # get the time place and description
            for ev in eventPost:
                if ev['type'] == 'Event':
                    if ev.get('postId'):
                        postId = ev['postId']
                    if ev.get('startTime'):
                        eventDate = \
                            datetime.strptime(ev['startTime'],
                                              "%Y-%m-%dT%H:%M:%S%z")
                        eventTime = eventDate.strftime("%H:%M").strip()
                    if 'public' in ev:
                        if ev['public'] is True:
                            eventIsPublic = True
                    if ev.get('sender'):
                        # get display name from sending actor
                        if ev.get('sender'):
                            senderActor = ev['sender']
                            dispName = \
                                getDisplayName(baseDir, senderActor,
                                               personCache)
                            if dispName:
                                senderName = \
                                    '' + \
                                    dispName + ': '
                    if ev.get('name'):
                        eventDescription = ev['name'].strip()
                elif ev['type'] == 'Place':
                    if ev.get('name'):
                        eventPlace = ev['name']
            # prepend a link to the sender of the calendar item
            if senderName and eventDescription:
                # if the sender is also mentioned within the event
                # description then this is a reminder
                senderActor2 = senderActor.replace('/users/', '/@')
                if senderActor not in eventDescription and \
                   senderActor2 not in eventDescription:
                    eventDescription = senderName + eventDescription
                else:
                    eventDescription = \
                        translate['Reminder'] + ': ' + eventDescription
            deleteButtonStr = ''
            if postId:
                deleteButtonStr = \
                    '\n \n'
            eventClass = 'calendar__day__event'
            calItemClass = 'calItem'
            if eventIsPublic:
                eventClass = 'calendar__day__event__public'
                calItemClass = 'calItemPublic'
            if eventTime and eventDescription and eventPlace:
                calendarStr += \
                    '![' + \
                    translate['Delete this event'] + ' ' + \
                    translate['Delete this event'] + ' |](/' + \
                    'icons/delete.png) | ' + \
                    '| ' + eventTime + \
                    ' | ' + \
                    '' + \
                    eventPlace + ' ' + deleteButtonStr + '' + eventDescription + \
                    '
 | 
\n'
            elif eventTime and eventDescription and not eventPlace:
                calendarStr += \
                    '' + \
                    '| ' + eventTime + \
                    ' | ' + \
                    eventDescription + '' + deleteButtonStr + ' | 
\n'
            elif not eventTime and eventDescription and not eventPlace:
                calendarStr += \
                    '' + \
                    '| ' + \
                    ' | ' + \
                    eventDescription + '' + deleteButtonStr + ' | 
\n'
            elif not eventTime and eventDescription and eventPlace:
                calendarStr += \
                    '' + \
                    '| ' + \
                    ' | ' + \
                    eventPlace + ' ' + deleteButtonStr + '' + eventDescription + \
                    '
 | 
\n'
            elif eventTime and not eventDescription and eventPlace:
                calendarStr += \
                    '' + \
                    '| ' + eventTime + \
                    ' | ' + \
                    '' + \
                    eventPlace + '' + \
                    deleteButtonStr + ' | 
\n'
    calendarStr += '\n'
    calendarStr += '
\n'
    calendarStr += htmlFooter()
    return calendarStr
def htmlCalendar(personCache: {}, cssCache: {}, translate: {},
                 baseDir: str, path: str,
                 httpPrefix: str, domainFull: str,
                 textModeBanner: str, accessKeys: {}) -> str:
    """Show the calendar for a person
    """
    domain = removeDomainPort(domainFull)
    monthNumber = 0
    dayNumber = None
    year = 1970
    actor = httpPrefix + '://' + domainFull + path.replace('/calendar', '')
    if '?' in actor:
        first = True
        for p in actor.split('?'):
            if not first:
                if '=' in p:
                    if p.split('=')[0] == 'year':
                        numStr = p.split('=')[1]
                        if numStr.isdigit():
                            year = int(numStr)
                    elif p.split('=')[0] == 'month':
                        numStr = p.split('=')[1]
                        if numStr.isdigit():
                            monthNumber = int(numStr)
                    elif p.split('=')[0] == 'day':
                        numStr = p.split('=')[1]
                        if numStr.isdigit():
                            dayNumber = int(numStr)
            first = False
        actor = actor.split('?')[0]
    currDate = datetime.now()
    if year == 1970 and monthNumber == 0:
        year = currDate.year
        monthNumber = currDate.month
    nickname = getNicknameFromActor(actor)
    if os.path.isfile(baseDir + '/img/calendar-background.png'):
        if not os.path.isfile(baseDir + '/accounts/calendar-background.png'):
            copyfile(baseDir + '/img/calendar-background.png',
                     baseDir + '/accounts/calendar-background.png')
    months = ('January', 'February', 'March', 'April',
              'May', 'June', 'July', 'August', 'September',
              'October', 'November', 'December')
    monthName = translate[months[monthNumber - 1]]
    if dayNumber:
        dayEvents = None
        events = \
            getTodaysEvents(baseDir, nickname, domain,
                            year, monthNumber, dayNumber)
        if events:
            if events.get(str(dayNumber)):
                dayEvents = events[str(dayNumber)]
        return _htmlCalendarDay(personCache, cssCache,
                                translate, baseDir, path,
                                year, monthNumber, dayNumber,
                                nickname, domain, dayEvents,
                                monthName, actor)
    events = \
        getCalendarEvents(baseDir, nickname, domain, year, monthNumber)
    prevYear = year
    prevMonthNumber = monthNumber - 1
    if prevMonthNumber < 1:
        prevMonthNumber = 12
        prevYear = year - 1
    nextYear = year
    nextMonthNumber = monthNumber + 1
    if nextMonthNumber > 12:
        nextMonthNumber = 1
        nextYear = year + 1
    print('Calendar year=' + str(year) + ' month=' + str(monthNumber) +
          ' ' + str(weekDayOfMonthStart(monthNumber, year)))
    if monthNumber < 12:
        daysInMonth = \
            (date(year, monthNumber + 1, 1) - date(year, monthNumber, 1)).days
    else:
        daysInMonth = \
            (date(year + 1, 1, 1) - date(year, monthNumber, 1)).days
    # print('daysInMonth ' + str(monthNumber) + ': ' + str(daysInMonth))
    cssFilename = baseDir + '/epicyon-calendar.css'
    if os.path.isfile(baseDir + '/calendar.css'):
        cssFilename = baseDir + '/calendar.css'
    calActor = actor
    if '/users/' in actor:
        calActor = '/users/' + actor.split('/users/')[1]
    instanceTitle = \
        getConfigParam(baseDir, 'instanceTitle')
    headerStr = htmlHeaderWithExternalStyle(cssFilename, instanceTitle)
    # the main graphical calendar as a table
    calendarStr = '\n'
    calendarStr += '\n'
    calendarStr += \
        '  '
    calendarStr += \
        '  ![' + translate['Previous month'] + ' ' + translate['Previous month'] + \
        '](/icons' + \
        '/prev.png) \n'
    calendarStr += '  '
    calendarStr += '
\n'
    calendarStr += '  '
    calendarStr += '  ' + monthName + '
\n'
    calendarStr += \
        '  '
    calendarStr += \
        '  ![' + translate['Next month'] + ' ' + translate['Next month'] + \
        '](/icons' + \
        '/prev.png) \n'
    calendarStr += '\n'
    calendarStr += '\n'
    calendarStr += '
\n'
    calendarStr += '\n'
    calendarStr += '\n'
    calendarStr += '\n'
    days = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat')
    for d in days:
        calendarStr += '  \n'
    calendarStr += '
\n'
    calendarStr += '\n'
    calendarStr += '\n'
    # beginning of the links used for accessibility
    navLinks = {}
    timelineLinkStr = htmlHideFromScreenReader('🏠') + ' ' + \
        translate['Switch to timeline view']
    navLinks[timelineLinkStr] = calActor + '/inbox'
    dayOfMonth = 0
    dow = weekDayOfMonthStart(monthNumber, year)
    for weekOfMonth in range(1, 7):
        if dayOfMonth == daysInMonth:
            continue
        calendarStr += '  \n'
        for dayNumber in range(1, 8):
            if (weekOfMonth > 1 and dayOfMonth < daysInMonth) or \
               (weekOfMonth == 1 and dayNumber >= dow):
                dayOfMonth += 1
                isToday = False
                if year == currDate.year:
                    if currDate.month == monthNumber:
                        if dayOfMonth == currDate.day:
                            isToday = True
                if events.get(str(dayOfMonth)):
                    url = calActor + '/calendar?year=' + \
                        str(year) + '?month=' + \
                        str(monthNumber) + '?day=' + str(dayOfMonth)
                    dayDescription = monthName + ' ' + str(dayOfMonth)
                    dayLink = '' + \
                        str(dayOfMonth) + ''
                    # accessibility menu links
                    menuOptionStr = \
                        htmlHideFromScreenReader('📅') + ' ' + \
                        dayDescription
                    navLinks[menuOptionStr] = url
                    # there are events for this day
                    if not isToday:
                        calendarStr += \
                            '    | ' + \
                            dayLink + '\n'
                    else:
                        calendarStr += \
                            ' | ' + \
                            dayLink + '\n'
                else:
                    # No events today
                    if not isToday:
                        calendarStr += \
                            ' | ' + \
                            str(dayOfMonth) + '\n'
                    else:
                        calendarStr += \
                            ' | ' + str(dayOfMonth) + '\n'
            else:
                calendarStr += ' | \n'
        calendarStr += ' | 
\n'
    calendarStr += '\n'
    calendarStr += '
\n'
    # end of the links used for accessibility
    nextMonthStr = \
        htmlHideFromScreenReader('→') + ' ' + translate['Next month']
    navLinks[nextMonthStr] = calActor + '/calendar?year=' + str(nextYear) + \
        '?month=' + str(nextMonthNumber)
    prevMonthStr = \
        htmlHideFromScreenReader('←') + ' ' + translate['Previous month']
    navLinks[prevMonthStr] = calActor + '/calendar?year=' + str(prevYear) + \
        '?month=' + str(prevMonthNumber)
    navAccessKeys = {
    }
    screenReaderCal = \
        htmlKeyboardNavigation(textModeBanner, navLinks, navAccessKeys,
                               monthName)
    return headerStr + screenReaderCal + calendarStr + htmlFooter()