import base64
import datetime
import hashlib
import os

from loguru import logger
from sqlalchemy import Column, DateTime, Integer, String, Unicode

from flexget import db_schema, plugin
from flexget.event import event
from flexget.utils.sqlalchemy_utils import table_add_column, table_columns
from flexget.utils.template import RenderError, get_template, render_from_entry

logger = logger.bind(name='make_rss')
Base = db_schema.versioned_base('make_rss', 0)

rss2gen = True
try:
    import PyRSS2Gen
except ImportError:
    rss2gen = False


@db_schema.upgrade('make_rss')
def upgrade(ver, session):
    if ver is None:
        columns = table_columns('make_rss', session)
        if 'rsslink' not in columns:
            logger.info('Adding rsslink column to table make_rss.')
            table_add_column('make_rss', 'rsslink', String, session)
        ver = 0
    return ver


class RSSEntry(Base):
    __tablename__ = 'make_rss'

    id = Column(Integer, primary_key=True)
    title = Column(Unicode)
    description = Column(Unicode)
    link = Column(String)
    rsslink = Column(String)
    file = Column(Unicode)
    published = Column(DateTime, default=datetime.datetime.utcnow)
    enc_length = Column(Integer)
    enc_type = Column(String)


class OutputRSS:
    """
    Write RSS containing succeeded (downloaded) entries.

    Example::

      make_rss: ~/public_html/flexget.rss

    You may write into same file in multiple tasks.

    Example::

      my-task-A:
        make_rss: ~/public_html/series.rss
        .
        .
      my-task-B:
        make_rss: ~/public_html/series.rss
        .
        .

    With this example file series.rss would contain succeeded
    entries from both tasks.

    **Number of days / items**

    By default output contains items from last 7 days. You can specify
    different perioid, number of items or both. Value -1 means unlimited.

    Example::

      make_rss:
        file: ~/public_html/series.rss
        days: 2
        items: 10

    Generate RSS that will containing last two days and no more than 10 items.

    Example 2::

      make_rss:
        file: ~/public_html/series.rss
        days: -1
        items: 50

    Generate RSS that will contain last 50 items, regardless of dates.

    RSS feed properties:

    You can specify the URL, title, and description to include in tthe header
    of the RSS feed.

    Example::

      make_rss:
        file: ~/public_html/series.rss
        rsslink: http://my.server.net/series.rss
        rsstitle: The Flexget RSS Feed
        rssdesc: Episodes about Flexget.

    **RSS item title and link**

    You can specify the title and link for each item in the RSS feed.

    The item title can be any pattern that references fields in the input entry.

    The item link can be created from one of a list of fields in the input
    entry, in order of preference. The fields should be enumerated in a list.
    Note that the url field is always used as last possible fallback even
    without explicitly adding it into the list.

    Default field list for item URL: imdb_url, input_url, url

    Example::

      make_rss:
        file: ~/public_html/series.rss
        title: '{{title}} (from {{task}})'
        link:
          - imdb_url

    """

    schema = {
        'oneOf': [
            {'type': 'string'},  # TODO: path / file
            {
                'type': 'object',
                'properties': {
                    'file': {'type': 'string'},
                    'days': {'type': 'integer'},
                    'items': {'type': 'integer'},
                    'history': {'type': 'boolean'},
                    'timestamp': {'type': 'boolean'},
                    'rsslink': {'type': 'string'},
                    'rsstitle': {'type': 'string'},
                    'rssdesc': {'type': 'string'},
                    'encoding': {'type': 'string'},  # TODO: only valid choices
                    'title': {'type': 'string'},
                    'template': {'type': 'string'},
                    'link': {'type': 'array', 'items': {'type': 'string'}},
                },
                'required': ['file'],
                'additionalProperties': False,
            },
        ]
    }

    def on_task_output(self, task, config):
        # makes this plugin count as output (stops warnings about missing outputs)
        pass

    def prepare_config(self, config):
        if not isinstance(config, dict):
            config = {'file': config}
        config.setdefault('days', 7)
        config.setdefault('items', -1)
        config.setdefault('history', True)
        config.setdefault('encoding', 'UTF-8')
        config.setdefault('timestamp', False)
        config.setdefault('link', ['imdb_url', 'input_url'])
        config.setdefault('title', '{{title}} (from {{task}})')
        config.setdefault('template', 'rss')
        # add url as last resort
        config['link'].append('url')
        return config

    def on_task_exit(self, task, config):
        """Store finished / downloaded entries at exit"""
        if not rss2gen:
            raise plugin.PluginWarning('plugin make_rss requires PyRSS2Gen library.')
        config = self.prepare_config(config)

        # when history is disabled, remove everything from backlog on every run (a bit hackish, rarely useful)
        if not config['history']:
            logger.debug('disabling history')