#!/usr/bin/python3
from flask import Flask, redirect, request, render_template, url_for
import pickle
import os
import random

def getRandomTags(aNum):
    with open("./tags.pickle","rb") as pickleFile:
        tagDict = pickle.load(pickleFile)
        allKeys = list(tagDict.keys())
        randKeys = random.sample(allKeys, min(aNum,len(allKeys)))
        return randKeys

def booleanOperator(listA, listB, operator):
    setA = set(listA)
    setB = set(listB)
    if operator=='and':
        return list(setA.intersection(setB))
    elif operator=='or':
        return list(setA.union(setB))
    elif operator=='not':   #this is really the binary operator: 'A (and not) B'
        return list(setA.difference(setB))

def parsePostfix(searchString):
    searchList = searchString.split('-')
    #replace each string in the list with its search result list, unless it's an operator
    with open("./tags.pickle","rb") as pickleFile:
        tagDict = pickle.load(pickleFile)
        for i in range(len(searchList)):
            if searchList[i] not in ['and','or','not']:
                searchList[i] = tagDict[searchList[i]]
    cursor = 0
    while len(searchList)>1:#walk through searchList, executing operators when encountered
        if cursor>=len(searchList): #reached the end and ran out of operators, 'and' everything that remains
            searchList[0] = booleanOperator(searchList[0], searchList.pop(1), 'and')
        elif searchList[cursor] in ['and','or','not']:
            searchList[cursor-2] = booleanOperator(searchList[cursor-2], searchList.pop(cursor-1), searchList.pop(cursor-1))
            cursor -= 2 #adjust for both pops
        cursor += 1
    outputList = []
    with open("./tags.pickledhash","rb") as hashFile:
        hashDict = pickle.load(hashFile)
    for result in searchList[0]:
        ext = result.split('.')[-1]
        if result in tagDict['image']:
            outputList.append((result,'image',ext,hashDict[result]))
        elif result in tagDict['video']:
            outputList.append((result,'video',ext,hashDict[result]))
        else:
            outputlist.append((result,'other',ext,hashDict[result]))
    return outputList

DIR_FOLDER = os.path.join('static','nudaDir')

app = Flask(__name__, template_folder="templates", static_folder="static")
app.config['DIR_FOLDER'] = DIR_FOLDER

numImages = 100

@app.route('/')
def home():
    return render_template('home.html', icon = os.path.join('static','nuda-icon.svg'))

@app.route('/', methods=['POST'])
def home_post():
    search = request.form['searchbox']
    hyphensearch = '-'.join(search.split(' '))
    return redirect(url_for('search', keyword=hyphensearch))

@app.route('/<keyword>')
@app.route('/<keyword>/<int:page>')
def search(keyword,page=None):
    imageList = [(f[0][10:],f[1],f[2],f[3]) for f in parsePostfix(keyword)]
    if page is None:
        page = 1
        full_filenames = [(os.path.join(app.config['DIR_FOLDER'], f[0]),f[1],f[2],f[3]) for f in imageList[numImages*(page-1):numImages*page]]
    else:
        full_filenames = [(os.path.join("..", app.config['DIR_FOLDER'], f[0]),f[1],f[2],f[3]) for f in imageList[numImages*(page-1):numImages*page]]
    return render_template("search.html", images = full_filenames, keyword = keyword, prevthisnext = [page-1, page, page+1], randTags = getRandomTags(10))

@app.route('/<keyword>', methods=['POST'])
@app.route('/<keyword>/<int:page>', methods=['POST'])
def search_post(keyword,page=None):
    search = request.form['searchbox']
    hyphensearch = '-'.join(search.split(' '))
    return redirect(url_for('search', keyword=hyphensearch))

if __name__ == "__main__":
    app.run(debug=True, port=8001, host='0.0.0.0')
