__filename__ = "follow.py"
__author__ = "Bob Mottram"
__license__ = "AGPL3+"
__version__ = "0.0.1"
__maintainer__ = "Bob Mottram"
__email__ = "bob@freedombone.net"
__status__ = "Production"

import json
from pprint import pprint
import os
import sys
from person import validUsername

def followPerson(baseDir: str,username: str, domain: str, followUsername: str, followDomain: str, federationList, followFile='following.txt') -> bool:
    """Adds a person to the follow list
    """
    if followDomain.lower().replace('\n','') not in federationList:
        return False
    handle=username.lower()+'@'+domain.lower()
    handleToFollow=followUsername.lower()+'@'+followDomain.lower()
    if not os.path.isdir(baseDir+'/accounts/'+handle):
        os.mkdir(baseDir+'/accounts/'+handle)
    filename=baseDir+'/accounts/'+handle+'/'+followFile
    if os.path.isfile(filename):
        if handleToFollow in open(filename).read():
            return True
        with open(filename, "a") as followfile:
            followfile.write(handleToFollow+'\n')
            return True
    with open(filename, "w") as followfile:
        followfile.write(handleToFollow+'\n')
    return True

def followerOfPerson(baseDir: str,username: str, domain: str, followerUsername: str, followerDomain: str, federationList) -> bool:
    """Adds a follower of the given person
    """
    return followPerson(baseDir,username, domain, followerUsername, followerDomain, federationList, 'followers.txt')

def unfollowPerson(baseDir: str,username: str, domain: str, followUsername: str, followDomain: str,followFile='following.txt') -> None:
    """Removes a person to the follow list
    """
    handle=username.lower()+'@'+domain.lower()
    handleToUnfollow=followUsername.lower()+'@'+followDomain.lower()
    if not os.path.isdir(baseDir+'/accounts/'+handle):
        os.mkdir(baseDir+'/accounts/'+handle)
    filename=baseDir+'/accounts/'+handle+'/'+followFile
    if os.path.isfile(filename):
        if handleToUnfollow not in open(filename).read():
            return
        with open(filename, "r") as f:
            lines = f.readlines()
        with open(filename, "w") as f:
            for line in lines:
                if line.strip("\n") != handleToUnfollow:
                    f.write(line)

def unfollowerOfPerson(username: str, domain: str, followerUsername: str, followerDomain: str) -> None:
    """Remove a follower of a person
    """
    unfollowPerson(username, domain, followerUsername, followerDomain,'followers.txt')

def clearFollows(baseDir: str,username: str, domain: str,followFile='following.txt') -> None:
    """Removes all follows
    """
    handle=username.lower()+'@'+domain.lower()
    if not os.path.isdir(baseDir+'/accounts/'+handle):
        os.mkdir(baseDir+'/accounts/'+handle)
    filename=baseDir+'/accounts/'+handle+'/'+followFile
    if os.path.isfile(filename):
        os.remove(filename)

def clearFollowers(baseDir: str,username: str, domain: str) -> None:
    """Removes all followers
    """
    clearFollows(baseDir,username, domain,'followers.txt')

def getNoOfFollows(baseDir: str,username: str,domain: str, followFile='following.txt') -> int:
    """Returns the number of follows or followers
    """
    handle=username.lower()+'@'+domain.lower()
    filename=baseDir+'/accounts/'+handle+'/'+followFile
    if not os.path.isfile(filename):
        return 0
    ctr = 0
    with open(filename, "r") as f:
        lines = f.readlines()
        for line in lines:
            if '#' not in line:
                if '@' in line and '.' in line and not line.startswith('http'):
                    ctr += 1
                elif line.startswith('http') and '/users/' in line:
                    ctr += 1
    return ctr

def getNoOfFollowers(username: str,domain: str) -> int:
    """Returns the number of followers of the given person
    """
    return getNoOfFollows(username,domain,'followers.txt')

def getFollowingFeed(baseDir: str,domain: str,port: int,path: str,https: bool,followsPerPage=12,followFile='following') -> {}:
    """Returns the following and followers feeds from GET requests
    """
    if '/'+followFile not in path:
        return None
    # handle page numbers
    headerOnly=True
    pageNumber=None    
    if '?page=' in path:
        pageNumber=path.split('?page=')[1]
        if pageNumber=='true':
            pageNumber=1
        else:
            try:
                pageNumber=int(pageNumber)
            except:
                pass
        path=path.split('?page=')[0]
        headerOnly=False
    
    if not path.endswith('/'+followFile):
        return None
    username=None
    if path.startswith('/users/'):
        username=path.replace('/users/','',1).replace('/'+followFile,'')
    if path.startswith('/@'):
        username=path.replace('/@','',1).replace('/'+followFile,'')
    if not username:
        return None
    if not validUsername(username):
        return None
            
    prefix='https'
    if not https:
        prefix='http'

    if port!=80 and port!=443:
        domain=domain+':'+str(port)

    if headerOnly:
        following = {
            '@context': 'https://www.w3.org/ns/activitystreams',
            'first': prefix+'://'+domain+'/users/'+username+'/'+followFile+'?page=1',
            'id': prefix+'://'+domain+'/users/'+username+'/'+followFile,
            'totalItems': getNoOfFollows(username,domain),
            'type': 'OrderedCollection'}
        return following

    if not pageNumber:
        pageNumber=1

    nextPageNumber=int(pageNumber+1)
    following = {
        '@context': 'https://www.w3.org/ns/activitystreams',
        'id': prefix+'://'+domain+'/users/'+username+'/'+followFile+'?page='+str(pageNumber),
        'orderedItems': [],
        'partOf': prefix+'://'+domain+'/users/'+username+'/'+followFile,
        'totalItems': 0,
        'type': 'OrderedCollectionPage'}        

    handle=username.lower()+'@'+domain.lower()
    filename=baseDir+'/accounts/'+handle+'/'+followFile+'.txt'
    if not os.path.isfile(filename):
        return following
    currPage=1
    pageCtr=0
    totalCtr=0
    with open(filename, "r") as f:
        lines = f.readlines()
        for line in lines:
            if '#' not in line:
                if '@' in line and '.' in line and not line.startswith('http'):
                    pageCtr += 1
                    totalCtr += 1
                    if currPage==pageNumber:
                        url = prefix + '://' + line.lower().replace('\n','').split('@')[1] + \
                            '/users/' + line.lower().replace('\n','').split('@')[0]
                        following['orderedItems'].append(url)
                elif line.startswith('http') and '/users/' in line:
                    pageCtr += 1
                    totalCtr += 1
                    if currPage==pageNumber:
                        following['orderedItems'].append(line.lower().replace('\n',''))
            if pageCtr>=followsPerPage:
                pageCtr=0
                currPage += 1
    following['totalItems']=totalCtr
    lastPage=int(totalCtr/followsPerPage)
    if lastPage<1:
        lastPage=1
    if nextPageNumber>lastPage:
        following['next']=prefix+'://'+domain+'/users/'+username+'/'+followFile+'?page='+str(lastPage)
    return following