# -*- coding: utf-8 -*-
"""
:copyright: (c) 2016 by <NAME>
:license: CC0 1.0 Universal, see LICENSE for more details.
"""

import os
import json
import uuid
import requests

from flask import current_app, session

try:
    # python 3
    from urllib.parse import urlparse
except ImportError:
    from urlparse import urlparse


# from bearlib.tools import baseDomain
def baseDomain(domain, includeScheme=True):
    """Return only the network location portion of the given domain
    unless includeScheme is True
    """
    result = ''
    url    = urlparse(domain)
    if includeScheme:
        result = '%s://' % url.scheme
    if len(url.netloc) == 0:
        result += url.path
    else:
        result += url.netloc
    return result

def kakuEvent(eventType, eventAction, eventData):
    """Publish a Kaku event.

    A Kaku event is used to allow async handling of events
    from web requests.

    Event Types: mention, post, login
    Event Actions: created, updated, deleted
    Event Data: a dictionary of items relevant to the event

    The event is stored in the location key generated and that
    key is then published to the event queue.
    """
    key  = 'kaku-event::%s::%s::%s' % (eventType, eventAction, str(uuid.uuid4()))
    data = { 'type':   eventType,
             'action': eventAction,
             'data':   eventData,
             'key':    key
           }
    current_app.dbRedis.set(key, json.dumps(data))
    current_app.dbRedis.publish(current_app.config['SITE_EVENTS'], key)

def clearAuth():
    if 'indieauth_token' in session:
        if current_app.dbRedis is not None:
            key = current_app.dbRedis.get('token-%s' % session['indieauth_token'])
            if key:
                current_app.dbRedis.delete(key)
                current_app.dbRedis.delete('token-%s' % session['indieauth_token'])
    session.pop('indieauth_token', None)
    session.pop('indieauth_scope', None)
    session.pop('indieauth_id',    None)

def checkAuth():
    authed       = False
    indieauth_id = None
    if 'indieauth_id' in session and 'indieauth_token' in session:
        current_app.logger.info('session cookie found')
        indieauth_id    = session['indieauth_id']
        indieauth_token = session['indieauth_token']
        if current_app.dbRedis is not None:
            key = current_app.dbRedis.get('token-%s' % indieauth_token)
            if key:
                data = current_app.dbRedis.hgetall(key)
                if data and data['token'] == indieauth_token:
                    authed = True
    return authed, indieauth_id

def checkAccessToken(access_token):
    if access_token is not None and current_app.dbRedis is not None:
        key = current_app.dbRedis.get('token-%s' % access_token)
        if key:
            data      = key.split('-')
            me        = data[1]
            client_id = data[2]
            scope     = data[3]
            current_app.logger.info('access token valid [%s] [%s] [%s]' % (me, client_id, scope))
            return me, client_id, scope
        else:
            return None, None, None
    else:
        return None, None, None

def validateAccessToken(token):
    try:
        if token:
            token = token.replace('Bearer ', '')
        me, client_id, scope = checkAccessToken(token)
        current_app.logger.info('[%s] [%s] [%s] [%s]' % (token, me, client_id, scope))
        if me is None or client_id is None:
            return me, client_id, scope, False
        else:
            return me, client_id, scope, True
    except:
        current_app.logger.exception('Exception during access token validation')
    return None, None, None, None, False

def validateDomain(domain):
    idDomain = baseDomain(current_app.config['CLIENT_ID'], includeScheme=False)
    return domain == idDomain

def validURL(targetURL):
    """Validate the target URL exists by making a HEAD request for it
    """
    result = 404
    try:
        r = requests.head(targetURL)
        result = r.status_code
    except:
        result = 404
    return result

def extractHCard(mf2Data):
    result = { 'name': '',
               'url':  '',
             }
    if 'items' in mf2Data:
        for item in mf2Data['items']:
            if 'type' in item and 'h-card' in item['type']:
                result['name'] = item['properties']['name']
                if 'url' in item['properties']:
                    result['url'] = item['properties']['url']
    return result

def generateSafeName(sourceURL):
    urlData = urlparse(sourceURL)
    result  = '%s_%s.mention' % (urlData.netloc, urlData.path.replace('/', '_'))
    return result

def generateMentionName(targetURL, vouched, cfg):
    urlData     = urlparse(targetURL)
    urlPaths    = urlData.path.split('/')
    basePath    = '/'.join(urlPaths[2:-1])
    mentionPath = os.path.join(cfg.paths.content, 'content', basePath)
    mentionSlug = urlPaths[-1]
    nMax        = 0

    if vouched:
        mentionExt = '.mention'
    else:
        mentionExt = '.mention_notvouched'

    for f in os.listdir(mentionPath):
        if f.endswith(mentionExt) and f.startswith(mentionSlug):
            try:
                n = int(f.split('.')[-2])
            except:
                n = 0
            if n > nMax:
                nMax = n
    return os.path.join(mentionPath, '%s.%03d%s' % (mentionSlug, nMax + 1, mentionExt))

# -*- coding: utf-8 -*-
"""
:copyright: (c) 2016 by <NAME>
:license: CC0 1.0 Universal, see LICENSE for more details.
"""

import os
import json
import uuid
import requests

from flask import current_app, session

try:
    # python 3
    from urllib.parse import urlparse
except ImportError:
    from urlparse import urlparse


# from bearlib.tools import baseDomain
def baseDomain(domain, includeScheme=True):
    """Return only the network location portion of the given domain
    unless includeScheme is True
    """
    result = ''
    url    = urlparse(domain)
    if includeScheme:
        result = '%s://' % url.scheme
    if len(url.netloc) == 0:
        result += url.path
    else:
        result += url.netloc
    return result

def kakuEvent(eventType, eventAction, eventData):
    """Publish a Kaku event.

    A Kaku event is used to allow async handling of events
    from web requests.

    Event Types: mention, post, login
    Event Actions: created, updated, deleted
    Event Data: a dictionary of items relevant to the event

    The event is stored in the location key generated and that
    key is then published to the event queue.
    """
    key  = 'kaku-event::%s::%s::%s' % (eventType, eventAction, str(uuid.uuid4()))
    data = { 'type':   eventType,
             'action': eventAction,
             'data':   eventData,
             'key':    key
           }
    current_app.dbRedis.set(key, json.dumps(data))
    current_app.dbRedis.publish(current_app.config['SITE_EVENTS'], key)

def clearAuth():
    if 'indieauth_token' in session:
        if current_app.dbRedis is not None:
            key = current_app.dbRedis.get('token-%s' % session['indieauth_token'])
            if key:
                current_app.dbRedis.delete(key)
                current_app.dbRedis.delete('token-%s' % session['indieauth_token'])
    session.pop('indieauth_token', None)
    session.pop('indieauth_scope', None)
    session.pop('indieauth_id',    None)

def checkAuth():
    authed       = False
    indieauth_id = None
    if 'indieauth_id' in session and 'indieauth_token' in session:
        current_app.logger.info('session cookie found')
        indieauth_id    = session['indieauth_id']
        indieauth_token = session['indieauth_token']
        if current_app.dbRedis is not None:
            key = current_app.dbRedis.get('token-%s' % indieauth_token)
            if key:
                data = current_app.dbRedis.hgetall(key)
                if data and data['token'] == indieauth_token:
                    authed = True
    return authed, indieauth_id

def checkAccessToken(access_token):
    if access_token is not None and current_app.dbRedis is not None:
        key = current_app.dbRedis.get('token-%s' % access_token)
        if key:
            data      = key.split('-')
            me        = data[1]
            client_id = data[2]
            scope     = data[3]
            current_app.logger.info('access token valid [%s] [%s] [%s]' % (me, client_id, scope))
            return me, client_id, scope
        else:
            return None, None, None
    else:
        return None, None, None

def validateAccessToken(token):
    try:
        if token:
            token = token.replace('Bearer ', '')
        me, client_id, scope = checkAccessToken(token)
        current_app.logger.info('[%s] [%s] [%s] [%s]' % (token, me, client_id, scope))
        if me is None or client_id is None:
            return me, client_id, scope, False
        else:
            return me, client_id, scope, True
    except:
        current_app.logger.exception('Exception during access token validation')
    return None, None, None, None, False

def validateDomain(domain):
    idDomain = baseDomain(current_app.config['CLIENT_ID'], includeScheme=False)
    return domain == idDomain

def validURL(targetURL):
    """Validate the target URL exists by making a HEAD request for it
    """
    result = 404
    try:
        r = requests.head(targetURL)
        result = r.status_code
    except:
        result = 404
    return result

def extractHCard(mf2Data):
    result = { 'name': '',
               'url':  '',
             }
    if 'items' in mf2Data:
        for item in mf2Data['items']:
            if 'type' in item and 'h-card' in item['type']:
                result['name'] = item['properties']['name']
                if 'url' in item['properties']:
                    result['url'] = item['properties']['url']
    return result

def generateSafeName(sourceURL):
    urlData = urlparse(sourceURL)
    result  = '%s_%s.mention' % (urlData.netloc, urlData.path.replace('/', '_'))
    return result

def generateMentionName(targetURL, vouched, cfg):
    urlData     = urlparse(targetURL)
    urlPaths    = urlData.path.split('/')
    basePath    = '/'.join(urlPaths[2:-1])
    mentionPath = os.path.join(cfg.paths.content, 'content', basePath)
    mentionSlug = urlPaths[-1]
    nMax        = 0

    if vouched:
        mentionExt = '.mention'
    else:
        mentionExt = '.mention_notvouched'

    for f in os.listdir(mentionPath):
        if f.endswith(mentionExt) and f.startswith(mentionSlug):
            try:
                n = int(f.split('.')[-2])
            except:
                n = 0
            if n > nMax:
                nMax = n
    return os.path.join(mentionPath, '%s.%03d%s' % (mentionSlug, nMax + 1, mentionExt))

# -*- coding: utf-8 -*- :copyright: (c) 2016 by <NAME> :license: CC0 1.0 Universal, see LICENSE for more details. # python 3 # from bearlib.tools import baseDomain Return only the network location portion of the given domain     unless includeScheme is True Publish a Kaku event.      A Kaku event is used to allow async handling of events     from web requests.      Event Types: mention, post, login     Event Actions: created, updated, deleted     Event Data: a dictionary of items relevant to the event      The event is stored in the location key generated and that     key is then published to the event queue. Validate the target URL exists by making a HEAD request for it