from utils import clean_articles
import ldap as l
from ldap3 import Server, Connection, ALL, MODIFY_REPLACE
from flask import Flask, g, request, session, redirect, url_for, render_template, send_from_directory
from flask_simpleldap import LDAP
from flask_bootstrap import Bootstrap
import os
import sqlite3
import requests
from utils import clean_articles, get_article
from flask_cache_buster import CacheBuster


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))'

short_domain = os.environ.get('SHORT_DOMAIN')

ldap = LDAP(app)

config = {
     'extensions': ['.js', '.css', '.csv'],
     'hash_size': 10
}

cache_buster = CacheBuster(config=config)
cache_buster.register_cache_buster(app)

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("/manifest.json")
def manifest():
    return send_from_directory('./', 'manifest.json')


@app.route('/')
@ldap.login_required
def index():
    user_dict = ldap.get_object_details(session['user_id'])

    if 'user_id' in session:
        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'),
        }

    conn = sqlite3.connect('pocket/readitlater.db')
    c = conn.cursor()

    c.execute("SELECT article_id, url, title, byline FROM saved_articles INNER JOIN articles on saved_articles.article_id = articles.id WHERE user=? AND read=0 OR read IS NULL", (session['user_id'], ))
    rows = c.fetchall()

    conn.commit()
    conn.close()

    return render_template('list.j2', articles = rows)


@app.route('/archived')
@ldap.login_required
def archived():
    conn = sqlite3.connect('pocket/readitlater.db')
    c = conn.cursor()

    c.execute("SELECT article_id, url, title, byline FROM saved_articles INNER JOIN articles on saved_articles.article_id = articles.id WHERE user=? AND read=1", (session['user_id'], ))
    rows = c.fetchall()
    print(rows)

    conn.commit()
    conn.close()

    return render_template('list.j2', articles = rows)


@app.route('/bookmarklet')
@ldap.login_required
def bookmarklet():
    return render_template('bookmarklet.j2')


@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']

            if 'next_redirect' in session:
                next = session['next_redirect']
                session['next_redirect'] = ''
                return redirect(next)
            return redirect('/')
    return render_template('login.j2')


@ldap.login_required
@app.route('/article/<int:article_id>')
def read_article(article_id):
    conn = sqlite3.connect('pocket/readitlater.db')
    c = conn.cursor()

    # c.execute("SELECT * FROM articles where id=?", (article_id,))
    c.execute("SELECT articles.id, url, content, title, byline, read FROM articles INNER JOIN saved_articles on saved_articles.article_id = articles.id WHERE articles.id=?", (article_id, ))
    
    rows = c.fetchall()
    conn.commit()
    conn.close()
    
    if (len(rows) > 0):
        return render_template('article.j2', article=rows[0])

    return render_template('article.j2', article=())


@ldap.login_required
@app.route('/add', methods=['GET', 'POST'])
def add_url():
    if not 'user_id' in session:
        session['next_redirect'] = request.url
        return redirect(url_for('login'))
    if request.method == 'POST':
        url = request.form['url']
        close = None
    else:
        url = request.args.get('url')
        close = request.args.get('close')
    conn = sqlite3.connect('pocket/readitlater.db')
    c = conn.cursor()

    if url is not None and len(url) > 0:
        article, short_domain = get_article(url)

        c.execute("SELECT * FROM articles WHERE url=?", (url,))
        rows = c.fetchall()
        
        if (len(rows) == 0):
            c.execute("INSERT INTO articles (url, content, title, byline) VALUES (?, ?, ?, ?)", (url, article['content'], article['title'], short_domain))
            c.execute("SELECT * FROM articles WHERE url=?", (url,))
            rows = c.fetchall()

        article_id = rows[0][0]

        c.execute("SELECT * FROM saved_articles WHERE user=? AND article_id=?", (session['user_id'], article_id))
        rows = c.fetchall()

        if (len(rows) == 0):
            c.execute("INSERT INTO saved_articles (user, article_id) VALUES (?, ?)", (session['user_id'], article_id))
        conn.commit()
        conn.close()

        if close is not None and close == '1':
            return render_template('close.j2')
        return 'Saved'
    conn.commit()
    conn.close()
    return 'Error'

@ldap.login_required
@app.route('/delete/<int:article_id>')
def delete_article(article_id):
    conn = sqlite3.connect('pocket/readitlater.db')
    c = conn.cursor()

    c.execute("DELETE FROM saved_articles WHERE user=? AND article_id=?", (session['user_id'], article_id))
    c.execute("SELECT * FROM saved_articles WHERE article_id=?", (article_id, ))
    rows = c.fetchall()
    
    if (len(rows) == 0):
        c.execute("DELETE FROM articles WHERE id=?", (article_id,))

    conn.commit()
    conn.close()

    return redirect(url_for('index'))

@ldap.login_required
@app.route('/archive/<int:article_id>')
def archive_article(article_id):
    conn = sqlite3.connect('pocket/readitlater.db')
    c = conn.cursor()

    c.execute("UPDATE saved_articles SET read=1 WHERE user=? AND article_id=?", (session['user_id'], article_id))

    conn.commit()
    conn.close()

    return redirect(url_for('index'))


@ldap.login_required
@app.route('/unarchive/<int:article_id>')
def unarchive_article(article_id):
    conn = sqlite3.connect('pocket/readitlater.db')
    c = conn.cursor()

    c.execute("UPDATE saved_articles SET read=0 WHERE user=? AND article_id=?", (session['user_id'], article_id))

    conn.commit()
    conn.close()

    return redirect(url_for('archived'))


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


if __name__ == '__main__':
    app.run()