import os
import xml.etree.ElementTree as ET
import json
from datetime import datetime, timezone
from html import escape
from pwd import getpwnam
from zipfile import ZipFile, BadZipFile
from uuid import uuid4

import db
from feeds import fetch_feeds_icon
from common import *


######################################################################
##### export OPML
def export_opml():
    opml = """\
<?xml version="1.0" encoding="utf-8"?>
<!-- OPML generated by MyNewspaper on %s -->
<opml version="1.0">
  <head>
    <title>MyNewspaper feeds</title>
    <dateCreated>%s</dateCreated>
    <dateModified>%s</dateModified>
    <ownerName>%s</ownerName>
    <ownerEmail>%s</ownerEmail>
  </head>
  <body>
%s
  </body>
</opml>
"""
    hostname = os.uname().nodename
    try:
        username = os.environ['USER']
        name = getpwnam(username).pw_gecos
    except KeyError:
        username = 'unknown'
        name = 'Unknown User'
    email = '%s@%s' % (username, hostname)
    d = datetime.now().strftime('%a, %d %b %Y %H:%M:%S %Z')
    buf = []
    for g in db.get_groups(sort=True):
        buf.append('    <outline title="%s">' % g.name)
        for f in g.get_feeds(sort=True):
            name = escape(f.name)
            buf.append('      <outline text="%s" description="%s" title="%s"' % (name, name, name))
            buf.append('               type="rss" version="RSS" language="unknown"')
            buf.append('               htmlUrl="%s" xmlUrl="%s" />' % (escape(f.link), escape(f.url)))
        buf.append('    </outline>')
    return opml % (d, d, d, name, email, '\n'.join(buf))


######################################################################
##### import OPML
def import_opml(buf):
    try:
        root = ET.fromstring(buf)
    except ET.ParseError:
        return False
    for g in root.findall('./body/outline'):
        gtitle = g.get('title')
        if not gtitle:
            continue
        group = db.group_new(gtitle)
        for f in g.findall('outline'):
            ftitle = f.get('title')
            furl = f.get('xmlUrl')
            flink = f.get('htmlUrl')
            if not ftitle or not furl:
                continue
            db.feed_new(ftitle, furl, flink, group.gid, delay_icon=True)
    fetch_feeds_icon(list(db.get_feeds(False)))
    return True


######################################################################
##### import from Google Reader takeout file
def import_from_googlereader(zipfile):
    try:
        with ZipFile(zipfile) as zf:
            opmlfile = starredfile = None
            for f in zf.namelist():
                if f.endswith('subscriptions.xml'):
                    opmlfile = f
                elif f.endswith('starred.json'):
                    starredfile = f
            if not opmlfile or not import_opml(zf.read(opmlfile)):
                return False
            if starredfile:
                import_starred_from_googlereader(zf.read(starredfile))
            return True
    except BadZipFile:
        return False


def import_starred_from_googlereader(buf):
    try:
        j = json.loads(buf.decode())
    except ValueError:
        return
    except UnicodeDecodeError:
        return
    if not 'items' in j:
        return
    for a in j['items']:
        title = a['title'] if 'title' in a else 'No title'
        try:
            url = a['alternate'][0]['href'] if 'alternate' in a and 'href' in a['alternate'][0] else ''
        except:
            url = ''
        contents = a['summary']['content'] if 'summary' in a and 'content' in a['summary'] else 'No contents'
        timestamp = datetime.fromtimestamp(a['updated'], tz=timezone.utc) if 'updated' in a else datetime.utcnow()
        uid = url if url!='' else uuid4().hex
        furl = a['origin']['streamId'][5:] if 'origin' in a and 'streamId' in a['origin'] else ''
        if furl != '':
            try:
                fid = db.Feed().get_by_url(furl).fid
            except db.DBFeedNotExistException:
                fid = 0
        else:
            fid = 0
        log.debug('Importing article: {} into feed #{}'.format(title, fid))
        db.article_new(uid, title, url, contents, timestamp, fid, state=STARRED, delay_commit=False)


######################################################################
