import glob
import configparser
import random
import base64

import requests
import flask
import flask_wtf.csrf
import waitress
import markdown

from post import Post

app = flask.Flask(__name__, static_url_path='', static_folder='static')

# CONFIG
CONFIG_PATH = "./config.ini"
config = configparser.ConfigParser()
config.read(CONFIG_PATH)

POSTS_FOLDER = config['POSTS']['POSTS_FOLDER']
STATUS_FILE = config['STATUS']['STATUS_FILE']
PORT = int(config['NETWORK']['PORT'])
DEV = int(config['NETWORK']['DEV'])


# CSRF Protect
app.config['SECRET_KEY'] = base64.b64decode(config["FLASK"]["SECRET"])
csrf = flask_wtf.csrf.CSRFProtect()
csrf.init_app(app)

MUSIC_API_TOKEN = config['AUTH']['MUSIC_API_TOKEN']
MUSIC_API_URL = config['NETWORK']['MUSIC_API_URL']
statuses = {}
header_background_images = [
    "canal-banner2.jpg",
    "real-greensilt-banner.png"
]

def get_posts(category_filter : str | None = None) -> list[tuple[dict, list]]:
    post_files = glob.glob(f'{POSTS_FOLDER}/*')
    try:
        post_files.remove(f'{POSTS_FOLDER}/POST_TEMPLATE.md')
    except ValueError as e:
        print(e)
        print(f'Couldn\'t remove the template file probably; {post_files}')
        exit()

    posts: list[Post] = []
    for post_file in post_files:
        post = Post(post_file)

        if not category_filter:
            posts.append(post)
        elif category_filter == post.category:
            posts.append(post)

    # Order Posts by Date
    ordered_posts = []
    for i in range(len(posts)):

        most_recent = posts[0]
        for p in posts:
            if p.date < most_recent.date:
                most_recent = p

        ordered_posts.append(most_recent)
        posts.remove(most_recent)

    # Convert to dict
    posts = []
    for post in reversed(ordered_posts):
        posts.append(post.__dict__)

    return posts

def read_status_file() -> dict:
    with open(STATUS_FILE, 'r', encoding='utf-8') as file:
        data = file.readlines()

    result = {}
    current_key = None
    for line in data:
        if line[0] == '#':

            # Empty Key-Value pairs will cause errors
            if current_key:
                if not result[current_key]:
                    result.pop(current_key)

            current_key = line.replace('#', '').strip()
            result[current_key] = []
        elif not (line == '\n'):
            result[current_key].append(line)

    return result

def get_status() -> str:
    keys = list(statuses.keys())

    selected_key = keys[random.randint(0, len(keys) - 1)]
    section: list = statuses[selected_key]

    selected_status = section[random.randint(0, len(section) - 1)]

    return f'<div title="{selected_key}">{markdown.markdown(selected_status)}</div>'

def get_header_image() -> str:
    return header_background_images[random.randint(0, len(header_background_images) - 1)]

# Main Page
@app.route('/')
def index():

    # Get posts
    posts = get_posts()

    # Get status
    status = get_status()

    img = get_header_image()

    return flask.render_template('index.html', posts=posts, status=status, title='0x01fe.net', header_background_image=img)

# Posts
@app.route('/post/<string:post_name>')
def post(post_name: str):

    for post in get_posts():
        if post['title'] == post_name:

            return flask.render_template('index.html', posts=[post], status=get_status(), title='0x01fe.net')

    flask.abort(404)

# Category's Endpoint
@app.route('/category/<string:category>/')
def category_filter(category: str):

    # Get posts
    posts = get_posts(category_filter=category)

    # Get status
    status = get_status()

    return flask.render_template('index.html', posts=posts, status=status, title=category.replace('-', ' '))

# Music Page
@app.route('/music/')
def music():

    # Get posts
    posts = get_posts(category_filter="music")

    # Get status
    status = get_status()

    # Get top albums
    r = requests.get(
        MUSIC_API_URL +'/top/albums',
        headers={
            'token' : MUSIC_API_TOKEN,
            'user' : '1',
            'limit' : '9'
        })

    top_albums = r.json()['top']
    for album_index in range(0, len(top_albums)):
        album = top_albums[album_index]

        time = int(album['listen_time'])
        hours = round(time/1000/60/60, 1)

        top_albums[album_index]['listen_time'] = hours


    return flask.render_template('music.html', posts=posts, status=status, top_albums=top_albums)

# Programming Page
@app.route('/programming/')
def programming():

    # Get posts
    posts_and_comments = get_posts(category_filter="programming")

    # Get status
    status = get_status()

    return flask.render_template('programming.html', posts=posts_and_comments, status=status)

# About Page
@app.route('/about/')
def about():

    # Get status
    status = get_status()

    return flask.render_template('about.html', status=status)

# MISC

@app.route('/albumsquare/<user_id>/<int:rows>')
def album_square(user_id, rows : int):

    limit = rows ** 2

    res = (1080/(rows))-rows

    # Get top albums
    r = requests.get(
        MUSIC_API_URL +'/top/albums',
        headers={
            'token' : MUSIC_API_TOKEN,
            'user' : user_id,
            'limit' : str(limit)
        })

    top_albums = r.json()['top']
    for album_index in range(0, len(top_albums)):
        album = top_albums[album_index]

        time = int(album['listen_time'])
        hours = round(time/1000/60/60, 1)

        top_albums[album_index]['listen_time'] = hours


    return flask.render_template('album_square.html', top_albums=top_albums, limit=rows, res=res)



if __name__ == "__main__":

    statuses = read_status_file()

    if DEV:
        app.run(port=PORT)
    else:
        waitress.serve(app, host='0.0.0.0', port=PORT)
