# Copyright (C) 2012 Science and Technology Facilities Council.
# Copyright (C) 2015-2018 East Asian Observatory.
#
# 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 calendar
from datetime import datetime
import socket

import cherrypy
from PyRSS2Gen import RSS2, RSSItem, Guid

from crab import CrabStatus
from crab.util.bus import CrabStoreListener


class CrabRSS(CrabStoreListener):
    """Class providing a RSS feed."""

    def __init__(self, bus, base_url):
        """Constructor for CrabRSS class.

        Caches the host's domain name for use in constructing GUIDs.
        Links includes in the RSS feed will use the given
        base URL."""

        super(CrabRSS, self).__init__(bus)

        self.base = base_url
        self.fqdn = socket.getfqdn()

    @cherrypy.expose
    def failures(self):
        """CherryPy handler to make an RSS feed of failures."""

        # TODO: make limit configurable (in CherryPy App .ini file)
        events = self.store.get_fail_events(limit=20)

        # Attach output
        for fail in events:
            fail['stdout'] = None
            fail['stderr'] = None

            if fail['finishid'] is not None:
                (fail['stdout'], fail['stderr']) = self.store.get_job_output(
                        fail['finishid'], fail['host'], fail['user'],
                        fail['id'], fail['crabid'])

        rssitems = [self.event_to_rssitem(e) for e in events]

        rss = RSS2('Crab failures', self.base + '/',
                   'List of recent cron job failures.',
                   lastBuildDate=datetime.now(),
                   ttl=30,
                   items=rssitems)
        return rss.to_xml()

    def event_to_rssitem(self, event):
        """Function converting an event (Python dict) to an RSSItem object."""

        title = (CrabStatus.get_name(event['status']) + ': ' +
                 event['user'] + ' @ ' + event['host'])
        if event['command'] is not None:
            title += ': ' + event['command']
        link = self.base + '/job/' + str(event['id'])
        if event['finishid'] is not None:
            link += '/output/' + str(event['finishid'])
        output = ''
        if event['stdout']:
            output += event['stdout']
        if event['stderr']:
            if event['stdout']:
                output += '\n\nStandard Error:\n\n'
            output += event['stderr']

        date = event['datetime']

        guid = ':'.join([
            'crab', self.fqdn, str(event['id']),
            str(calendar.timegm(date.timetuple())), str(event['status'])])

        info = {}

        if output != '':
            info['description'] = '<pre>' + output + '</pre>'

        return RSSItem(title=title,
                       link=link,
                       pubDate=date,
                       guid=Guid(guid, isPermaLink=False),
                       **info)
