"""
Routines for handling RSS feeds
"""

import itertools
import subprocess
import os
import re
import operator
import datetime
import sys
import mimetypes
import logging
import argparse

import feedparser
import jaraco.logging
from pathvalidate import sanitize_filename
from dateutil import parser as date_parser

from jaraco.net.http import get_url

log = logging.getLogger(__name__)


def parse_filter(filter_string):
    filter_pattern = re.compile('(?:(before|after) )?([0-9-]+)$', re.I)
    match = filter_pattern.match(filter_string)
    sign, date_string = match.groups()
    op = dict(before=operator.le, after=operator.ge).get(sign, operator.eq)
    spec_date = date_parser.parse(date_string)
    return lambda entry: op(datetime.datetime(*entry.updated_parsed[:6]), spec_date)


class CombinedFilter(list):
    """
    A list of callables that can be applied to a filter call.
    """

    def __call__(self, subject):
        return all(filter(subject) for filter in self)


def _parse_args(parser=None):
    parser = parser or argparse.ArgumentParser()
    parser.add_argument('url')
    parser.add_argument(
        '-f',
        '--date-filter',
        help="add a date filter such as 'before 2006'",
        default=CombinedFilter(),
        action="append",
        type=parse_filter,
    )
    jaraco.logging.add_arguments(parser)
    args = parser.parse_args()
    jaraco.logging.setup(args)
    return args


def download_enclosures():
    args = _parse_args()
    d = feedparser.parse(args.url)
    for entry in filter(args.date_filter, d['entries']):
        enclosure = entry.enclosures.pop()
        assert not entry.enclosures, "Only support one enclosure per item"

        title = entry.title
        ext = mimetypes.guess_extension(enclosure.type) or '.mp3'
        filename = title + ext
        log.info('Getting %s', filename)
        sanitized = sanitize_filename(filename, replacement_text='_')
        try:
            get_url(enclosure.url, sanitized, replace_newer=True)
        except KeyboardInterrupt:
            if os.path.exists(sanitized):
                os.remove(sanitized)
            log.info('Quitting')
            break


def launch_feed_enclosure():
    """
    RSS Feed Launcher
    """
    parser = argparse.ArgumentParser(usage=launch_feed_enclosure.__doc__)
    parser.add_argument('-i', '--index', help="launch feed found at specified index")
    args = _parse_args(parser)
    load_feed_enclosure(args.url, args.date_filter, args.index)


def load_feed_enclosure(url, filter_=None, index=None):
    d = feedparser.parse(url)
    print('loaded', d['feed']['title'])
    filtered_entries = filter(filter_, d['entries'])

    if index is None:
        for i, entry in enumerate(filtered_entries):
            fmt = str('{0:4d} {1}')
            print(fmt.format(i, entry.title))
        try:
            index = int(input('Which one? '))
        except ValueError:
            print("Nothing selected")
            sys.exit(0)

    player_search = (
        r'C:\Program Files\Windows Media Player\wmplayer.exe',
        r'C:\Program Files (x86)\Windows Media Player\wmplayer.exe',
    )
    player = next(itertools.ifilter(os.path.exists, player_search))

    command = [player, filtered_entries[index].enclosures[0].href]
    print('running', subprocess.list2cmdline(command))
    subprocess.Popen(command)


def launch_feed_as_playlist():
    options, args = _parse_args()
    assert not args, "Positional arguments not allowed"
    get_feed_as_playlist(options.url, filter_=options.date_filter)


def get_feed_as_playlist(url, outfile=sys.stdout, filter_=None):
    d = feedparser.parse(url)
    filtered_entries = filter(filter_, d['entries'])
    # RSS feeds are normally retrieved in reverse cronological order
    filtered_entries.reverse()
    for e in filtered_entries:
        outfile.write(e.enclosures[0].href)
        outfile.write('\n')


if __name__ == '__main__':
    launch_feed_enclosure()
