from flask import Flask,render_template,request,abort,jsonify
import json
import os
from xml.etree.ElementTree import Element,SubElement, tostring,ElementTree
import datetime
import functools
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
import csv
import hashlib

HOME_PATH=os.getcwd()
BIN_PATH=os.path.join(HOME_PATH,"bin")
HOMEWORK_METADATA_PATH=os.path.join(HOME_PATH,"homeworkMetadata.xml")
ADMININFO_PATH=os.path.join(HOME_PATH,"adminInfo.xml")
STUDENTLIST_PATH=os.path.join(HOME_PATH,"studentList.csv")
SECRET_KEY="abcdefghijk"

app = Flask(__name__)

def create_token(api_user):
    #第一个参数是内部的私钥，这里写在共用的配置信息里了，如果只是测试可以写死
    #第二个参数是有效期(秒)
    s = Serializer(SECRET_KEY,expires_in=3600)
    #接收用户id转换与编码
    token = s.dumps({"id":api_user})
    return str(token,encoding="utf-8")


def login_required(view_func):
    @functools.wraps(view_func)
    def verify_token(*args,**kwargs):
        try:
            #在请求头上拿到token
            token = request.headers["token"]
            token = bytes(token,encoding="utf-8")
        except Exception:
            #没接收的到token,给前端抛出错误
            #这里的code推荐写一个文件统一管理。这里为了看着直观就先写死了。
            return jsonify(code = 4103,msg = '缺少参数token')
        
        s = Serializer(SECRET_KEY)
        try:
            s.loads(token)
        except Exception:
            return jsonify(code = 4101,msg = "登录已过期")

        return view_func(*args,**kwargs)

    return verify_token


@app.route("/")
def root():
    homeworks=getAllHomeworks()
    '''
    for i in range(len(homeworks)):
        deadline=homeworks[i]["deadline"]
        deadline=datetime.datetime.strptime(deadline, '%Y-%m-%d %H:%M:%S')
        now=datetime.datetime.now()
        countdown=deadline-now
        #homeworks[i]["countdown"]=str(countdown)
        homeworks[i]["countdown"]="100000"
    '''
    return render_template('root.html',homeworks=homeworks)

@app.route("/upload",methods=["POST"])
def upload():
    homeworkName=request.form.get("homeworkName")
    if findHomework(homeworkName) is None:
        return error()
    name = request.form.get("name")
    num = request.form.get("num")
    uploadFile = request.files['file']
    folderPath=os.path.join(BIN_PATH,homeworkName)
    currentDateTime=datetime.datetime.now()
    uploadFile.save(os.path.join(folderPath,num+"_"+name+"_"+currentDateTime.strftime('%H-%M-%S')+"."+uploadFile.filename.split(".")[-1])) 
    return json.dumps({"result": 1})

@app.route("/contact")
def contact():
    return render_template("contact.html")

@app.route("/admin/login")
def adminLogin():
    return render_template('adminLogin.html')

@app.route("/admin/verify",methods=["POST"])
def adminVerify():
    username = request.form.get("username")
    password = request.form.get("password")
    if password=="123456" and username=="admin":
        return json.dumps({"result":True,"token":str(create_token(username))})
    else:
        return json.dumps({"result":False})

@app.route("/admin")
@login_required
def admin():
    allHomeworks=getAllHomeworks()
    return render_template("admin.html",homeworks=allHomeworks)

@app.route("/admin/<homework>")
@login_required
def homework(homework):
    currentInfo=getCurrentHomework(homework)
    return render_template("homework.html",data=currentInfo,homeworkName=homework)

@app.route("/admin/studentList")
@login_required
def studentList():
    studentList=getStudentList()
    return render_template('studentList.html',data=studentList)

@app.route("/admin/studentListFile",methods=["POST"])
@login_required
def studentListFile():
    uploadFile = request.files['file']
    uploadFile.save(STUDENTLIST_PATH) 
    return json.dumps({"result": 1})

@app.route("/admin/publish")
@login_required
def publish():
    return render_template('publish.html')

@app.route("/admin/newHomework",methods=["POST"])
@login_required
def newHomework():
    name = request.form.get("name")
    describe = request.form.get("describe")
    deadline=request.form.get("deadline")
    addHomework(name,describe,deadline)
    return json.dumps({"result": 1})

@app.route("/admin/cancel/<homework>",methods=["POST"])
@login_required
def cancelHomework(homework):
    deleteHomework(homework)
    return json.dumps({"result": 1})


def getCurrentHomework(homework):
    homeworkFolderPath=os.path.join(BIN_PATH,homework)
    if not os.path.exists(homeworkFolderPath):
        return error()
    #已经交
    homeworkFolder=os.listdir(homeworkFolderPath)
    if len(homeworkFolder)>0:
        for i in range(len(homeworkFolder)):
            homeworkFolder[i]=homeworkFolder[i].strip(".zip").split("_")[1]
    #未交
    studentList=getStudentList()
    result=[i+["yes"] if i[1] in homeworkFolder else i+["no"] for i in studentList ]
    return result
    


def getStudentList():
    with open(STUDENTLIST_PATH,encoding = 'utf-8-sig') as f:
        stuList=csv.reader(f)
        result=[i for i in stuList]
        return result

def getAllHomeworks():
    root=ElementTree().parse(HOMEWORK_METADATA_PATH)
    result=[]
    for homework in list(root):
        tempDict={"name":homework.find("name").text}
        tempDict["describe"]=homework.find("describe").text
        tempDict["deadline"]=homework.find("deadline").text
        result.append(tempDict)
    return result

def getHomeworkInfo(homework):
    tempDict={"name":homework.getElementsByTagName("name")}
    tempDict["describe"]=homework.getElementsByTagName("describe")
    tempDict["deadline"]=homework.getElementsByTagName("deadline")
    return tempDict

def findHomework(homeworkName):
    tree=ElementTree().parse(HOMEWORK_METADATA_PATH)
    homeworks=list(tree)
    for homework in homeworks:
        name=homework.find("name").text
        if homeworkName==name:
            return homework
    return None

def addHomework(name,describe,deadline):
    tree=ElementTree().parse(HOMEWORK_METADATA_PATH)
    tmp = SubElement(tree, "homework")
    SubElement(tmp, "name").text = name
    SubElement(tmp, "describe").text = describe
    SubElement(tmp, "deadline").text = deadline
    tree=ElementTree(tree)
    tree.write(HOMEWORK_METADATA_PATH,"utf-8")
    homeworkPath=os.path.join(BIN_PATH,name)
    if not os.path.exists(homeworkPath):
        os.mkdir(homeworkPath)

def deleteHomework(homeworkName):
    tree=ElementTree().parse(HOMEWORK_METADATA_PATH)
    homeworks=list(tree)
    for homework in homeworks:
        name=homework.find("name").text
        if homeworkName==name:
            tree.remove(homework)
            break
    tree=ElementTree(tree)
    tree.write(HOMEWORK_METADATA_PATH,"utf-8")


def error():
    return abort(404)




if __name__ == '__main__':
    app.run(host="127.0.0.1")