import datetime, os, re
from bottle import error, response, route, run, static_file, template, TEMPLATE_PATH

def list_rec(page):
    loc = 'diary/entries/'
    result = []
    rec = []
    comment = ""
    if isinstance(page, int):
        # Collect recommended articles from comment line
        with open('diary/entries/' + str(page)) as f:
            comment = f.readline()
        comment = comment.replace('<!--','')
        comment = comment.replace('-->','')
        comment = comment.replace(' ','')
        comment = clean(comment)
        rec = comment.split(',')
        # Convert into array for template to display
        for article in rec:
            if is_it_time(article):
                path = loc + article
                data = []
                try:
                    with open(path) as f:
                        f.readline()
                        data.append(clean(f.readline().replace('<br>','')))
                    data.append(path)
                    result.append(data)
                except EnvironmentError:
                    print("No article @ " + path)
    return result

# List latest 5 articles as headline links
def list_headlines(articles):
    loc = 'diary/entries/'
    result = []
    text = []
    for article in articles:
        path = loc + article
        b = []
        b.append(path)
        with open(path) as f:
            f.readline()
            text = f.readline()
        b.append(clean(text.replace('<br>','')))
        result.append(b)
    return result

# Return title of article, formatted for sharing via social media
def find_social_title(text):
    return clean(text[1]).replace(' ','+')

# Return URL of article
def find_url(path):
    return '/' + path.replace('.tpl','')

# Return clean timestamp
def find_timestamp(text):
    return text[2].replace('<br>','')

# Return clean title
def find_title(text):
    return clean(text[1])

# Return article as list of lines of text
def article2list(article, loc):
    text = []
    with open(loc + article) as f:
        text = f.readlines()
    return text

def retrieve_article(page, loc):
    text = []
    string = ""
    with open(loc + str(page)) as f:
        text = f.readlines()
    for line in text:
        string += line
    return string

# Return list of snippets using list of articles
def list_snippets(articles):
    loc = 'diary/entries/'
    limit = 4
    total = len(articles)
    result = []

    for article in articles:
        path = loc + article
        text = []
        a = []
        length = 0
        text = article2list(article, loc)
        a.append(find_title(text))
        a.append(prepare_article(text, path))
        a.append(find_timestamp(text))
        a.append(find_url(path))
        a.append(find_social_title(text))
        result.append(a)
    return result

# Return line count of file
def count_lines(fname):
    with open(fname) as f:
        for linenum, line in enumerate(f,1):
            pass
    return linenum

# Return article text without HTML header
def find_content(text):
    length = len(text)
    content = ""
    # form a string from relevant lines of the article
    pos = 0
    for line in text:
        # skip to line 5
        if pos > 4 and pos < length:
            content += line
        pos += 1
    return content

# Snip article and close any open list tags
def prepare_article(text, path):
    content = snip_article(find_content(text), path)
    if content.count('<ul>') > content.count('</ul>'):
        content += '</ul>'
    return content

# Remove links, line breaks from snippet
def clean(result):
    result = result.replace('\n','')
    result = result.replace('<br>','')
    result = re.sub(r'<a href=.*?>', '', result)
    result = re.sub(r'<img src=.*?>', '', result)
    result = re.sub(r'<a target="_blank" href=.*?>', '', result)
    result = result.replace('</a>','')
    result = re.sub(r'<h\d>','',result)
    result = re.sub(r'</h\d>','',result)
    result = result.replace('<center>','')
    result = result.replace('</center>','')
    result = result.replace('<b>','')
    result = result.replace('</b>','')
    return result

# Return first 300 words of article + " ... "
def snip_article(article, path):
    article = clean(article)
    limit = 300
    result = article[0:min(len(article),limit)]
    result = result.rsplit(' ',1)[0]
    return result + " ... "

# Sort diary - newest to oldest
def sort_files(files):
    files.sort(reverse=True)
    return files

def curate_files(files):
    # remove folders
    if 'raw' in files:
        files.remove('raw')
    if 'extra' in files:
        files.remove('extra')
    # remove 
    clean = []
    for f in files:
        if is_it_time(f):
            clean.append(f)
    return clean

def is_it_time(date):
    today = datetime.datetime.now()
    today_string = today.strftime("%y") + today.strftime("%m") + today.strftime("%d")
    return int(date) <= int(today_string)

# Return list of all diary entries (exclude raws + extras)
def gather_files(loc):
    files = os.listdir(loc)
    return files

def gather_and_sort(loc):
    return sort_files(curate_files(gather_files(loc)))

def fill_ideabox():
    box = []
    with open('diary/entries/extra/ideabox') as f:
        for line in f:
            box.append(line)
    return box

## Static ##

# Serve CSS
@route('/static/css/<filename:path>')
def serve_css(filename):
    return static_file(filename, root='static/css')

# Serve images
@route('/static/img/<filename:path>')
def serve_img(filename):
    return static_file(filename, root='static/img')

# Serve unlisted articles
@route('/static/extra/<filename:re:.*\.cpp>')
def serve_extra(filename):
    return static_file(filename, root='static/extra', mimetype='text/plain', download=True)

## Routes ##

# 404 Error Page
@error(404)
def error404(error):
    return "unfortunately, a 404 error"

# Downloads
@route('/download/<filename:path>')
def download(filename):
    return static_file(filename, root='static/extra', download=filename)

# Home Page - Index Template
@route('/')
def index():
    """home page"""
    loc = 'diary/entries/'
    info = {'css': 'index', 'news': list_headlines(gather_and_sort(loc)[0:10]), 'title': 'chimchooree\'s dev space - blessfrey', 'year': datetime.datetime.now()}
    return template('index.tpl', info)

# Projects Page - Game Template - system, character, story info
@route('/projects')
def projects():
    """projects page"""
    info = {'css': 'projects', 'title': 'chimchooree projects', 'year': datetime.datetime.now()}
    return template('projects.tpl', info)

# Presskit Page - Presskit Template - product, developer info
@route('/presskit')
def presskit():
    """press page"""
    info = {'css': 'presskit', 'title': 'blessfrey - presskit', 'year': datetime.datetime.now()}
    return template('presskit.tpl', info)

# Start on first Diary page if no page given
@route('/diary')
def diary2():
    return diary(0)

# Diary Page - Diary Template - list all articles
@route('/diary/<page:int>')
def diary(page):
    """diary page"""
    loc = 'diary/entries/'
    assert isinstance(page, int)
    info = {'css': 'diary', 'title': 'blessfrey - developer diary', 'year': datetime.datetime.now(), 'snippets': list_snippets(gather_and_sort(loc)), 'latest': list_headlines(gather_and_sort(loc)[0:5]), 'total': len(curate_files(gather_files(loc))), 'limit': 8, 'cluster': 3, 'page': page}
    return template('diary.tpl', info)

# Entry Page - Feature Template - for articles
@route('/diary/entries/<page:int>')
def entry(page):
    """diary entry"""
    if not is_it_time(page):
        return error404(404)
    loc = 'diary/entries/'
    info = {'css': 'feature', 'title': 'blessfrey - developer diary', 'year': datetime.datetime.now(), 'entry': retrieve_article(page, loc), 'recommends': list_rec(page), 'articles': "Articles", 'latest': list_headlines(gather_and_sort(loc)[0:5]), 'page': page}
    abs_app_dir_path = os.path.dirname(os.path.realpath(__file__))
    abs_views_path = os.path.join(abs_app_dir_path, 'views')
    TEMPLATE_PATH.insert(0, abs_views_path )
    return template(os.path.join(abs_views_path,'feature.tpl'), info)

# Extra Page - Feature Template - for unlisted articles
@route('/diary/entries/extra/<page>')
def extra(page):
    """diary extra"""
    loc = 'diary/entries/extra/'
    info = {'css': 'feature', 'title': 'blessfrey - developer diary', 'year': datetime.datetime.now(), 'entry': retrieve_article(page, loc), 'recommends': list_rec(page), 'articles': "Articles", 'latest': list_headlines(gather_and_sort('diary/entries/')[0:5]), 'page': page}
    abs_app_dir_path = os.path.dirname(os.path.realpath(__file__))
    abs_views_path = os.path.join(abs_app_dir_path, 'views')
    TEMPLATE_PATH.insert(0, abs_views_path )
    return template(os.path.join(abs_views_path,'feature.tpl'), info)

# Personal Page - Box Template
@route('/box')
def box():
    """personal page"""
    info = {'css': 'box', 'title': 'chimchooree\'s personal page', 'year': datetime.datetime.now()}
    return template('box.tpl', info)

# Credits Page - Credits Template
@route('/credits')
def credits():
    """credits page"""
    info = {'css': 'box', 'title': 'blessfrey - credits', 'year': datetime.datetime.now()}
    return template('credits.tpl', info)


# Contact Page - Contact Template
@route('/contact')
def contact():
    """contact page"""
    info = {'css': 'box', 'title': 'blessfrey - contact chimchooree', 'year': datetime.datetime.now()}
    return template('contact.tpl', info)

# Idea Box Page - Box Template
@route('/ideabox')
def ideabox():
    """idea box page"""
    info = {'css': 'box', 'title': 'blessfrey - idea box - a collection of inspiring concepts', 'words': fill_ideabox(), 'limit': 5, 'year': datetime.datetime.now()}
    return template('ideabox.tpl', info)

## Main ##

if __name__ == '__main__':
    run(host='127.0.0.1', port=9001)
