from flask import Flask, request, session, redirect, url_for, render_template, flash, jsonify, send_from_directory
from . models import Posts, db
from flask_cors import CORS, cross_origin
from app.forms import UploadForm
from app import app
from  sqlalchemy.sql.expression import func, select
from sqlalchemy.sql import except_
import re,string
import os
from werkzeug.utils import secure_filename
import json
from bs4 import BeautifulSoup

import subprocess
from subprocess import Popen, PIPE
from subprocess import check_output

basedir = os.path.abspath(os.path.dirname(__file__))
UPLOAD_FOLDER = os.path.join(basedir, 'img')

ALLOWED_EXTENSIONS = set([ 'png', 'jpg', 'jpeg', 'gif'])

def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

def cleanhtml(raw_html):
  cleanr = re.compile('<.*?>')
  cleantext = re.sub(cleanr, '', raw_html)
  return cleantext

@app.route('/')
@cross_origin(origin='*')
def index():
    posts = db.session.query(Posts).all()
    return render_template('index.html', posts=posts)

@app.route('/overview')
@cross_origin(origin='*')
def overview():
    posts = db.session.query(Posts).all()
    return render_template('home.html', posts=posts)

@app.route('/index')
def all():
    posts = db.session.query(Posts).all()
    return render_template('all.html', posts=posts)

@app.route('/<int:pid>')
@cross_origin(origin='*')
def post(pid):
    post = Posts.query.filter_by(pid=pid).first()
    return render_template('singlepost.html', post=post)

@app.route('/min/<int:pid>')
@cross_origin(origin='*')
def post_min(pid):
    post = Posts.query.filter_by(pid=pid).first()
    return render_template('singlepost_minimal.html', post=post)

@app.route('/<int:pid>/edit', methods=['GET', 'POST'])
@cross_origin(origin='*')
def edit_post(pid):
    post = Posts.query.filter_by(pid=pid).first()
    user_form = UploadForm(title = post.title, writingfield=post.writingfield, category=post.category)
    if request.method == 'POST':
        if user_form.validate_on_submit():
            # on submit, check fields
            post.title = user_form.title.data
            post.writingfield = user_form.writingfield.data
            post.category = user_form.category.data
            db.session.commit()
            return redirect(url_for('post', pid=pid))

    return render_template('writer.html', form=user_form, post=post)

@app.route('/<int:pid>/delete', methods=['GET', 'POST'])
@cross_origin(origin='*')
def delete_post(pid):
    post = Posts.query.filter_by(pid=pid).first()
    db.session.delete(post)
    db.session.commit()

    return redirect(url_for('index'))



@app.route('/writer', methods=['GET', 'POST'])
@cross_origin(origin='*')
def writer():
    post = Posts("unknown", "", "")
    user_form = UploadForm()
    if request.method == 'POST':
        if user_form.validate_on_submit():
            # on submit, check fields
            title = user_form.title.data
            writingfield = user_form.writingfield.data
            category = user_form.category.data
            post = Posts(title, writingfield, category)
            db.session.add(post)
            db.session.commit()
            return redirect(url_for('post', pid=post.pid))
    return render_template('writer.html',form=user_form, post=post )


@app.route('/uploadajax', methods=['POST'])
def uploadfile():
    if request.method == 'POST':
        files = request.files['file']
        if files and allowed_file(files.filename):
            filename = secure_filename(files.filename)
            app.logger.info('FileName: ' + filename)
            updir = os.path.join(basedir, 'img/')
            files.save(os.path.join(updir, filename))
            file_size = os.path.getsize(os.path.join(updir, filename))
            return jsonify(name=filename, size=file_size)


@app.route('/turninbinary', methods=['POST', 'GET'])
def truninbinary():
    if request.method == 'POST':
        files = request.files['file']
        filename = secure_filename(files.filename)
        app.logger.info('FileName: ' + filename)
        updir = os.path.join(basedir, 'binary/')
        files.save(os.path.join(updir, filename))

        p = subprocess.Popen(['cp', os.path.join(updir, filename), os.path.join(basedir, 'binary/input.raw')])
        p_status = p.wait()

        p = subprocess.Popen(['sox', '-r','22050', '-b','8', '-c','1', '-e','signed', os.path.join(basedir, 'binary/input.raw'),os.path.join(basedir, 'binary/audio.wav')])
        p_status = p.wait()

        p = subprocess.Popen(['ffmpeg','-y','-i',os.path.join(basedir, 'binary/audio.wav'),'-vn','-ar','44100','-ac','2','-f','mp3',os.path.join(basedir, 'binary/output.mp3')])
        p_status = p.wait()

        p = subprocess.Popen(['ffmpeg','-y','-f','rawvideo','-s','32x18','-i', os.path.join(basedir, 'binary/input.raw'), os.path.join(basedir, 'binary/video.mp4')])
        p_status = p.wait()

        p = subprocess.Popen(['ffmpeg','-y','-i', os.path.join(basedir, 'binary/video.mp4'),'-vf','scale=320:240', os.path.join(basedir, 'binary/output.mp4')])
        p_status = p.wait()

        p = subprocess.Popen(['ffmpeg','-y','-i',os.path.join(basedir, 'binary/output.mp4'),'-i',os.path.join(basedir, 'binary/output.mp3'),'-c','copy','-map','0:v:0','-map','1:a:0',os.path.join(basedir, 'binary/output_both.mp4')])
        p_status = p.wait()

        return send_from_directory(os.path.join(basedir, 'binary'), 'output_both.mp4')
        #subprocess.call(['cp', os.path.join(basedir, 'binary/file'), 'input.raw'])

    return render_template('turnfilein.html', )

@app.route('/img/<filename>')
def send_file(filename):
    return send_from_directory(UPLOAD_FOLDER, filename)

@app.route('/database')
def send_database():
    return send_from_directory(basedir, 'data.db')


###
# The API
###

@app.route('/api/beginwith=<query>', methods=['GET'])
def get_words(query):
    posts = Posts.query.all()
    data = []
    for post in posts:
        text = post.writingfield
        #text = cleanhtml(text)
        regex = re.compile('[%s]' % re.escape(string.punctuation))
        #text = regex.sub('', text)
        soup = BeautifulSoup(text,"lxml")
        for id, word in enumerate(soup.prettify().split()):
            if "<" not in word or ">" not in word or "=" not in word:
                word = regex.sub('', word)
                query = regex.sub('', query)
                if word.lower().startswith(query.lower()):
                    a = {}
                    a['word'] = word
                    a['intext'] = post.pid
                    a['intextname'] = post.title
                    a['wordnumber'] = id
                    try:
                        context = [
                        soup.prettify().split()[id-2],
                        soup.prettify().split()[id-1],
                        soup.prettify().split()[id],
                        soup.prettify().split()[id+1],
                        soup.prettify().split()[id+2]
                        ]
                    except:
                        context = [
                        "no", "context"
                        ]
                    a['context'] = ' '.join(context)
                    data.append(a)
    text = post.title
    #text = cleanhtml(text)
    #regex = re.compile('[%s]' % re.escape(string.punctuation))
    #text = regex.sub('', text)
    soup = BeautifulSoup(text,"lxml")
    for id, word in enumerate(soup.prettify().split()):
        if word.startswith(query) and ("<" not in word or ">" not in word or "=" not in word):
            a = {}
            a['word'] = word
            a['intext'] = post.pid
            a['intextname'] = post.title
            a['wordnumber'] = id
            context = [
            soup.prettify().split()[id-2],
            soup.prettify().split()[id-1],
            soup.prettify().split()[id],
            soup.prettify().split()[id+1],
            soup.prettify().split()[id+2]
            ]
            a['context'] = ' '.join(context)
            data.append(a)

    #print(errors)
    return jsonify(data)

@app.route('/api/link=<int:link>+wordnum=<int:n>+document=<int:pid>', methods=['GET'])
def replace_with(link, n, pid):
    post = Posts.query.filter_by(pid=pid).first()
    frompost = Posts.query.filter_by(pid=link).first()
    html = post.writingfield
    soup = BeautifulSoup(html,"lxml")
    words = soup.prettify().split()
    words[n] = words[n]+" <a class='linkTo' href='"+str(link)+"'>→ "+frompost.title+"</a>"
    print(words)
    post.writingfield = ' '.join(words)
    db.session.commit()


    return redirect(url_for('post', pid=pid))


@app.route('/api/getcontent', methods=['GET'])
def get_text():
    posts = Posts.query.all()
    data = {}

    for post in posts:
        content = post.writingfield
        soup = BeautifulSoup(content)
        removedLinks = []
        removedImg = []
        imgsub = []
        for a in soup.find_all("a", {'class':'linkTo'}):
            removedLinks.append(a.extract().get_text())
        for img in soup.find_all("img"):
            removedImg.append(img['src'])
        for subtitle in soup.find_all("span", {'class':'imgsub'}):
            imgsub.append(subtitle.extract().get_text())
        content = str(soup)
        soup = BeautifulSoup(content)
        content = str(soup.get_text(separator='\n'))
        content = re.sub(' +', ' ', content).strip()
        #content=re.sub("\s\s+" , " ", content)
        #content = str(soup)
        images = []
        for i,img in enumerate(removedImg):
            if i < len(imgsub):
                images.append({"url":img, "sub":imgsub[i]})
            else:
                images.append({"url":img, "sub":""})

        data[post.pid] = {"title":post.title, "category":post.category, "content":content, "removedLinks":removedLinks, "images":images}

    #print(errors)
    return jsonify(data)


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