# This file is part of Email-Reminder.
#
# Copyright (C) 2020 by Francois Marier
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.

from PySide2.QtCore import (
    Qt, QAbstractTableModel, QModelIndex)
from EmailReminder.Utils import readXMLValue, writeXMLValue


def parseDay(dayString, lastDay):
    try:
        day = int(dayString)
    except ValueError:
        return 1

    if day < 1:
        return 1
    if day > lastDay:
        return lastDay

    return day


class EventModel(QAbstractTableModel):
    TYPE = 'event'
    COLUMN_NAMES = ["Event Name"]

    def __init__(self, document):
        super().__init__()
        self.document = document
        self.events = []
        self.column_count = len(self.COLUMN_NAMES)

    def _createEvent(self):
        event = self.document.createElement('event')
        event.setAttribute('type', self.TYPE)
        self.fillNewEvent(event)

        user = self.document.getElementsByTagName('email-reminder_user')
        events = user.item(0).getElementsByTagName('events')
        events.item(0).appendChild(event)

        return event

    def fillNewEvent(self, event):
        writeXMLValue(self.document, event, 'name', '<New Event>')

        reminders = self.document.createElement('reminders')
        sameday = self.document.createElement('reminder')
        sameday.setAttribute('type', 'same day')
        reminders.appendChild(sameday)
        event.appendChild(reminders)

    def addEvent(self, event, parent=QModelIndex()):
        self.beginInsertRows(parent, len(self.events), len(self.events))
        self.events.append(event)
        self.endInsertRows()

    def rowCount(self, parent=QModelIndex()):
        # pylint: disable=unused-argument
        return len(self.events)

    def columnCount(self, parent=QModelIndex()):
        # pylint: disable=unused-argument
        return self.column_count

    def headerData(self, section, orientation, role):
        if role != Qt.DisplayRole:
            return None
        if orientation != Qt.Horizontal:
            return None
        return self.COLUMN_NAMES[section]

    def getDataInternal(self, column, row):
        if column == 0:
            return readXMLValue(self.events[row], 'name')

        return None

    def data(self, index, role=Qt.DisplayRole):
        column = index.column()
        row = index.row()

        if role in (Qt.DisplayRole, Qt.EditRole):
            return self.getDataInternal(column, row)

        return None

    def flags(self, index):
        # pylint: disable=unused-argument
        return Qt.ItemIsEditable | Qt.ItemIsEnabled | Qt.ItemIsSelectable

    def getReminders(self, row):
        sameDay = False
        daysInAdvance = 0

        event = self.events[row]
        reminderList = event.getElementsByTagName('reminders')
        if reminderList:
            reminders = reminderList.item(0).getElementsByTagName('reminder')
            for reminder in reminders:
                typeAttribute = reminder.getAttribute('type')
                if typeAttribute == 'same day':
                    sameDay = True
                elif typeAttribute == 'days before':
                    if reminder.hasChildNodes() and reminder.firstChild:
                        daysInAdvance = int(reminder.firstChild.nodeValue)

        return {'name': readXMLValue(self.events[row], 'name'),
                'sameday': sameDay,
                'daysinadvance': daysInAdvance}

    def deleteReminder(self, parent, typeName):
        reminders = parent.getElementsByTagName('reminder')
        for reminder in reminders:
            if reminder.getAttribute('type') == typeName:
                parent.removeChild(reminder)

    def setReminder(self, parent, typeName, nodeValue=None):
        # Look for an existing element to modify.
        for reminder in parent.getElementsByTagName('reminder'):
            if reminder.getAttribute('type') == typeName:
                if nodeValue:
                    if reminder.hasChildNodes():
                        reminder.firstChild.nodeValue = nodeValue
                    else:
                        reminder.appendChild(
                            self.document.createTextNode(str(nodeValue)))
                return  # nothing else to do

        # Create a new element.
        reminder = self.document.createElement('reminder')
        reminder.setAttribute('type', typeName)
        if nodeValue:
            reminder.appendChild(self.document.createTextNode(str(nodeValue)))
        parent.appendChild(reminder)

    def setReminders(self, row, values):
        event = self.events[row]
        reminderList = event.getElementsByTagName('reminders')
        if not reminderList:
            reminders = self.document.createElement('reminders')
            event.appendChild(reminders)

        if not values['sameday']:
            self.deleteReminder(reminderList.item(0), 'same day')
        else:
            self.setReminder(reminderList.item(0), 'same day')

        if values['daysinadvance'] == 0:
            self.deleteReminder(reminderList.item(0), 'days before')
        else:
            self.setReminder(reminderList.item(0), 'days before',
                             values['daysinadvance'])

    def setDataInternal(self, column, row, value):
        if column == 0:
            writeXMLValue(self.document, self.events[row], 'name', value)

    def setData(self, index, value, role=Qt.EditRole):
        if role != Qt.EditRole:
            return False

        column = index.column()
        row = index.row()
        self.setDataInternal(column, row, value)
        self.dataChanged.emit(index, index, [role])
        return True

    def insertRows(self, row, count, parent=QModelIndex()):
        if count < 1:
            return False

        # These are not currently needed.
        if count > 1:
            return False
        if row != self.rowCount():
            return False

        self.addEvent(self._createEvent(), parent)
        return True

    def removeRows(self, row, count, parent=QModelIndex()):
        if count < 1:
            return False

        # This is neither implemented nor currently needed.
        if count > 1:
            return False

        self.beginRemoveRows(parent, row, row)
        event = self.events[row]
        del self.events[row]
        event.parentNode.removeChild(event)
        self.endRemoveRows()

        return True

    def append(self):
        return self.insertRows(self.rowCount(), 1)

    def delete(self, row):
        return self.removeRows(row, 1)
