#!/usr/bin/env python3
# vim:ts=4:sw=4:ft=python:fileencoding=utf-8
# Copyright © 2015-2019 Carl Chenet <carl.chenet@ohmytux.com>
# 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
# 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/>

"""Checks an RSS feed and posts new entries to Mastodon."""

# standard libraires imports
import codecs
import importlib
import logging
import logging.handlers
import sys
import re

# external liraries imports
from bs4 import BeautifulSoup

# app libraries imports
from feed2toot.addtags import AddTags
from feed2toot.cliparse import CliParse
from feed2toot.confparse import ConfParse
from feed2toot.feedcache import FeedCache
from feed2toot.filterentry import FilterEntry
from feed2toot.hashtags import build_hashtags
from feed2toot.hashtags import extract_hashtags_from_list
from feed2toot.lock import LockFile
from feed2toot.message import build_message
from feed2toot.message import send_message_dry_run
from feed2toot.message import send_message
from feed2toot.plugins import activate_plugins
from feed2toot.removeduplicates import RemoveDuplicates
from feed2toot.rss import populate_rss
from feed2toot.sortentries import sort_entries
from feed2toot.tootpost import TootPost

class Main:
    '''Main class of Feed2toot'''

    def __init__(self):
        self.main()

    def setup_logging(self, options):
        if options.syslog:
            sl = logging.handlers.SysLogHandler(address='/dev/log')
            sl.setFormatter(logging.Formatter('feed2toot[%(process)d]: %(message)s'))
            # convert syslog argument to a numeric value
            loglevel = getattr(logging, options.syslog.upper(), None)
            if not isinstance(loglevel, int):
                raise ValueError('Invalid log level: %s' % loglevel)
            sl.setLevel(loglevel)
            logging.getLogger('').addHandler(sl)
            logging.debug('configured syslog level %s' % loglevel)
        logging.getLogger('').setLevel(logging.DEBUG)
        sh = logging.StreamHandler()
        sh.setLevel(options.log_level.upper())
        logging.getLogger('').addHandler(sh)
        logging.debug('configured stdout level %s' % sh.level)

    def main(self):
        '''The main function'''
        clip = CliParse()
        clioptions = clip.options
        self.setup_logging(clioptions)
        # iterating over the different configuration files
        cfgp = ConfParse(clioptions)
        confs = cfgp.confvalues
        for conf in confs:
            options = conf[0]
            config = conf[1]
            tweetformat = conf[2]
            feeds = conf[3]
            plugins = conf[4]
            # check the logfile and logtimeout
            lockfile = LockFile(options['lockfile'], options['locktimeout'])
            # create link to the persistent list
            cache = FeedCache(options)
            severalwordshashtags = extract_hashtags_from_list(options)
            # reverse feed entries because most recent one should be sent as the last one in Mastodon
            for feed in feeds:
                # store the patterns by rss
                if 'patterns' in feed:
                    patterns = feed['patterns']
                entries = feed['feed']['entries'][0:clioptions.limit]
                entries.reverse()
                # --rss-sections option: print rss sections and exit
                if clioptions.rsssections:
                    if entries:
                        print('The following sections are available in this RSS feed: {}'.format([j for j in entries[0]]))
                        sys.exit(0)
                    else:
                        sys.exit('Could not parse the section of the rss feed')
                # sort entries and check if they were not previously sent
                totweet = sort_entries(clioptions.all, cache, entries)
                for entry in totweet:
                    # populate rss with new entry to send
                    rss = populate_rss(entry)
                    rss = build_hashtags(entry, rss, options, severalwordshashtags)
                    # parse tweetfomat to elements
                    elements = re.findall(r"\{(.*?)\}",tweetformat)
                    # strip : from elements to allow string formating, eg. {title:.20}
                    for i,s in enumerate(elements):
                         if s.find(':'):
                             elements[i] = s.split(':')[0]
                    fe = FilterEntry(elements, entry, options, feed['patterns'], feed['rssobject'], feed['feedname'])
                    entrytosend = fe.finalentry
                    if entrytosend:
                        finaltweet = build_message(entrytosend, tweetformat, rss)
                        if clioptions.dryrun:
                            send_message_dry_run(config, entrytosend, finaltweet)
                        else:
                            send_message(config, clioptions, options, entrytosend, finaltweet, cache, rss)
                            # plugins
                            if plugins and entrytosend:
                                activate_plugins(plugins, finaltweet)
            # do not forget to close cache (shelf object)
            cache.close()
            # release the lock file
            lockfile.release()
