import ldap as l
from ldap3 import Server, Connection, ALL, MODIFY_REPLACE
from flask import Flask, g, request, session, redirect, url_for, render_template
from flask_bs4 import Bootstrap
from flask_simpleldap import LDAP
import yaml
import datetime as dt
import pytz
import os
import sqlite3

app = Flask(__name__)
Bootstrap(app)
app.secret_key = 'asdf'
app.debug = True

# Base
app.config['LDAP_REALM_NAME'] = 'OpenLDAP Authentication'
app.config['LDAP_HOST'] = os.environ.get('LDAP_HOST')
app.config['LDAP_BASE_DN'] = os.environ.get('LDAP_BASE_DN')
app.config['LDAP_USERNAME'] = os.environ.get('LDAP_USERNAME')
app.config['LDAP_PASSWORD'] = os.environ.get('LDAP_PASSWORD')

# OpenLDAP 
app.config['LDAP_OBJECTS_DN'] = 'dn'
app.config['LDAP_OPENLDAP'] = True
app.config['LDAP_USER_OBJECT_FILTER'] = '(&(objectclass=posixAccount)(uid=%s))'

ldap = LDAP(app)

eastern = pytz.timezone('US/Eastern')

with open('config/config.yaml') as f:
    yaml_data = yaml.load(f, Loader=yaml.SafeLoader)

search = yaml_data['search']
account_url = yaml_data['accounts']['account_url']

description = yaml_data['description']
game_description = yaml_data['game_description']

countdown_data = None
if yaml_data['countdown']['active'] == True:
    countdown_data = yaml_data['countdown']

final_countdown_data = None
final_time = None
if yaml_data['final_countdown']['active'] == True:
    final_countdown_data = yaml_data['final_countdown']
    final_time = eastern.localize(dt.datetime.strptime(final_countdown_data['timestamp'], '%B %d %Y %H:%M:%S%z').replace(tzinfo=None))

apps = []
for itm in yaml_data['apps'].items():
    apps.append(itm[1])


games = []
for itm in yaml_data['games'].items():
    games.append(itm[1])


server = Server(app.config['LDAP_HOST'])
conn = Connection(server, app.config['LDAP_USERNAME'], app.config['LDAP_PASSWORD'], auto_bind=True)


@app.before_request
def before_request():
    g.user = None
    if 'user_id' in session:
        # This is where you'd query your database to get the user info.
        g.user = {}


@app.route('/')
def index():
    current_time = eastern.localize(dt.datetime.now())
    if final_countdown_data != None:
        if (final_time - current_time).days > -1:
            return render_template('final_countdown.j2', final_countdown = final_countdown_data)
    if countdown_data != None:
        return render_template('index.j2', apps = apps, search = search, account_url = account_url, description = description, countdown = countdown_data)
    return render_template('index.j2', apps = apps, search = search, account_url = account_url, description = description)


@app.route('/games')
def game():
    if 'user_id' in session:
        user_dict = ldap.get_object_details(session['user_id'])
        user = {'dn': 'cn={},cn=usergroup,ou=users,dc=technicalincompetence,dc=club'.format(user_dict['cn'][0].decode('ascii')),
                'firstName': user_dict['givenName'][0].decode('ascii'),
                'lastName': user_dict['sn'][0].decode('ascii'),
                'email': user_dict['mail'][0].decode('ascii'),
                'userName': user_dict['uid'][0].decode('ascii'),
        }
    
    current_time = eastern.localize(dt.datetime.now())
    if final_countdown_data != None:
        if (final_time - current_time).days > -1:
            return render_template('final_countdown.j2', final_countdown = final_countdown_data)
    if countdown_data != None:
        return render_template('games.j2', apps = games, search = search, account_url = account_url, description = game_description, countdown = countdown_data)
    if 'user_id' in session:
        return render_template('games.j2', apps = games, search = search, account_url = account_url, description = game_description, user = user, game_list = generate_game_list())
    return render_template('games.j2', apps = games, search = search, account_url = account_url, description = game_description)


@app.route('/login', methods=['GET', 'POST'])
def login():
    if g.user:
        return redirect(url_for('index'))
    if request.method == 'POST':
        user = request.form['user']
        passwd = request.form['passwd']
        test = ldap.bind_user(user, passwd)
        if test is None or passwd == '':
            return render_template('login.j2', error='Invalid credentials')
        else:
            session['user_id'] = request.form['user']
            session['passwd'] = request.form['passwd']
            return redirect('/games')
    return render_template('login.j2')


@ldap.login_required
@app.route('/add', methods=['POST'])
def add_game():
    if request.method == 'POST':
        game_title = request.form['game_title']
        game_link = request.form['game_link']
        conn = sqlite3.connect('config/games_in_progress.db')
        c = conn.cursor()

        if game_title is not None and len(game_title) > 0 and game_link is not None and len(game_link) > 0:
            c.execute("INSERT INTO games (user_id, game_title, game_link) VALUES (?, ?, ?)", (session['user_id'], game_title, game_link,))
            conn.commit()
            conn.close()

            return 'Success'
        conn.commit()
        conn.close()
    return 'Error'


@ldap.login_required
@app.route('/delete', methods=['POST'])
def delete_game():
    if request.method == 'POST':
        game_id = request.form['game_id']
        conn = sqlite3.connect('config/games_in_progress.db')
        c = conn.cursor()

        if game_id is not None and len(game_id) > 0:
            c.execute("DELETE FROM games WHERE id=? AND user_id=?", (game_id, session['user_id'],))
            conn.commit()
            conn.close()

            return 'Success'
        conn.commit()
        conn.close()
    return 'Error'


def generate_game_list():
    conn = sqlite3.connect('config/games_in_progress.db')
    c = conn.cursor()

    if 'user_id' in session:
        c.execute('SELECT * FROM games WHERE user_id=?', (session['user_id'], ))
        rows = c.fetchall()
        conn.close()

        return rows

    conn.close()
    return []


@app.route('/logout')
def logout():
    session.pop('user_id', None)
    return redirect(url_for('game'))


if __name__ == '__main__':
    app.run(extra_files="config/config.yaml")
