import os
import json
import time

from flask import Flask, request, make_response, abort, render_template, session, jsonify, send_file

import base
import rest
import auth
from config import cfg

from actuator import Actuator
from watch import Watch
from listen import Listen
from space import Space
from dance import Dance
from talk import Talk


app = Flask(__name__)
app.secret_key=os.urandom(16)


@app.route("/", methods=["POST"])
def controller():
    token = request.form.get("token")
    if token == "": abort(401)
    if not auth.checktoken(token): abort(401)

    session["token"] = token
    
    return render_template("controller.html")


@app.route("/forward", methods=["POST"])
def forward():
    token = session["token"]
    if token == "": abort(401)
    if not auth.checktoken(token): abort(401)

    try:
        hr = Actuator.Forward(token)
        if hr:
            return make_response("success")
        else:
            return make_response("forward failed", 500)
        
    except Exception as e:
        abort(400)


@app.route("/backward", methods=["POST"])
def backward():
    token = session["token"]
    if token == "": abort(401)
    if not auth.checktoken(token): abort(401)

    try:
        hr = Actuator.Backward(token)
        if hr:
            return make_response("success")
        else:
            return make_response("backward failed", 500)
        
    except Exception as e:
        abort(400)


@app.route("/left", methods=["POST"])
def left():
    token = session["token"]
    if token == "": abort(401)
    if not auth.checktoken(token): abort(401)

    try:
        hr = Actuator.Left(token)
        if hr:
            return make_response("success")
        else:
            return make_response("left failed", 500)
        
    except Exception as e:
        abort(400)


@app.route("/right", methods=["POST"])
def right():
    token = session["token"]
    if token == "": abort(401)
    if not auth.checktoken(token): abort(401)

    try:
        hr = Actuator.Right(token)
        if hr:
            return make_response("success")
        else:
            return make_response("right failed", 500)
        
    except Exception as e:
        abort(400)


@app.route("/stop", methods=["POST"])
def stop():
    token = session["token"]
    if token == "": abort(401)
    if not auth.checktoken(token): abort(401)

    try:
        hr = Actuator.Stop(token)
        if hr:
            return make_response("success")
        else:
            return make_response("stop failed", 500)
        
    except Exception as e:
        abort(400)


@app.route("/watch/start", methods=["POST"])
def watchstart():
    token = session["token"]
    if token == "": abort(401)
    if not auth.checktoken(token): abort(401)

    if Watch.StartWatch(token) :
        return make_response("success")
    else:
        return make_response("start watch action error", 500)


@app.route("/watch/stop", methods=["POST"])
def watchstop():
    token = session["token"]
    if token == "": abort(401)
    if not auth.checktoken(token): abort(401)

    if Watch.StopWatch() :
        return make_response("success")
    else:
        return make_response("stop watch action error", 500)


@app.route("/watch/info", methods=["GET"])
def watchinfo():
    token = session["token"]
    if token == "": abort(401)
    if not auth.checktoken(token): abort(401)

    info = Watch.GetCurrentImageInfo()
    if info is None:
        return make_response("get watch info error", 500)
    else:
        return jsonify(info)


@app.route("/watch/data/<string:filename>", methods=["GET"])
def watchdata(filename):
    token = session["token"]
    if token == "": abort(401)
    if not auth.checktoken(token): abort(401)

    filedir = os.path.join(cfg.get("watch", "datadir"), filename)
    if os.path.isfile(filedir):
        return send_file(filedir)
    else:
        return send_file("static/img/empty.jpg")


@app.route("/listen/start", methods=["POST"])
def listenstart():
    token = session["token"]
    if token == "": abort(401)
    if not auth.checktoken(token): abort(401)

    if Listen.StartListen(token):
        return make_response("success")
    else:
        return make_response("start listen action error", 500)


@app.route("/listen/stop", methods=["POST"])
def listenstop():
    token = session["token"]
    if token == "": abort(401)
    if not auth.checktoken(token): abort(401)

    if Listen.StopListen():
        return make_response("success")
    else:
        return make_response("stop listen action error", 500)


@app.route("/listen/info", methods=["GET"])
def listeninfo():
    token = session["token"]
    if token == "": abort(401)
    if not auth.checktoken(token): abort(401)

    info = Listen.GetCurrentText()
    if info is None:
        return make_response("get listen info error", 500)
    else:
        return jsonify(info)


@app.route("/space/start", methods=["POST"])
def spacestart():
    token = session["token"]
    if token == "": abort(401)
    if not auth.checktoken(token): abort(401)
    
    reqjson = request.get_json()
    x = reqjson["x"]
    y = reqjson["y"]
    if x is None or y is None:
        return make_response('miss parameters', 400)

    if Space.StartAutoMove(token, base.Point(x,y)):
        return make_response("success")
    else:
        return make_response("start automoving action error", 500)


@app.route("/space/stop", methods=["POST"])
def spacestop():
    token = session["token"]
    if token == "": abort(401)
    if not auth.checktoken(token): abort(401)

    if Space.StopAutoMove():
        return make_response("success")
    else:
        return make_response("start automoving action error", 500)


@app.route("/space/info", methods=["GET"])
def spaceinfo():
    token = session["token"]
    if token == "": abort(401)
    if not auth.checktoken(token): abort(401)

    info = Space.GetRobotPosInfo()
    if info is None:
        return make_response("get space info error", 500)
    else:
        return jsonify(info)


@app.route("/space/map", methods=["GET"])
def spacemap():
    token = session["token"]
    if token == "": abort(401)
    if not auth.checktoken(token): abort(401)
        
    info = Space.GetMapPoints()
    if info is None:
        return make_response("get space map error", 500)
    else:
        return jsonify(info)


@app.route("/dance/start", methods=["POST"])
def dancestart():
    token = session["token"]
    if token == "": abort(401)
    if not auth.checktoken(token): abort(401)
    
    reqjson = request.get_json()
    music = reqjson["music"]
    if music is None:
        return make_response('miss parameters', 400)

    if Dance.StartDance(token, music) :
        return make_response("success")
    else:
        return make_response("start dancing action error", 500)


@app.route("/dance/stop", methods=["POST"])
def dancestop():
    token = session["token"]
    if token == "": abort(401)
    if not auth.checktoken(token): abort(401)
    
    if Dance.StopDance(token) :
        return make_response("success")
    else:
        return make_response("stop dancing action error", 500)


@app.route("/dance/musics", methods=["GET"])
def dancemusics():
    token = session["token"]
    if token == "": abort(401)
    if not auth.checktoken(token): abort(401)
    
    musics = Dance.GetMusics()
    return jsonify(musics)


@app.route("/dance/info", methods=["GET"])
def danceinfo():
    token = session["token"]
    if token == "": abort(401)
    if not auth.checktoken(token): abort(401)

    info = Dance.GetDanceInfo()
    if info is None:
        return make_response("get dance info error", 500)
    else:
        return jsonify(info)


@app.route("/talk/start", methods=["POST"])
def talkstart():
    token = session["token"]
    if token == "": abort(401)
    if not auth.checktoken(token): abort(401)
    
    reqjson = request.get_json()
    title = reqjson["title"]
    index = reqjson["index"]
    if title is None or index is None:
        return make_response('miss parameters', 400)

    if Talk.StartAct(token, title, index) :
        return make_response("success")
    else:
        return make_response("start talking action error", 500)


@app.route("/talk/stop", methods=["POST"])
def talkstop():
    token = session["token"]
    if token == "": abort(401)
    if not auth.checktoken(token): abort(401)
    
    if Talk.StopAct(token) :
        return make_response("success")
    else:
        return make_response("stop talking action error", 500)


@app.route("/talk/info", methods=["GET"])
def talkinfo():
    token = session["token"]
    if token == "": abort(401)
    if not auth.checktoken(token): abort(401)

    info = Talk.GetActInfo()
    if info is None:
        return make_response("get talk info error", 500)
    else:
        return jsonify(info)


@app.route("/talk/titles", methods=["GET"])
def talktitles():
    token = session["token"]
    if token == "": abort(401)
    if not auth.checktoken(token): abort(401)
    
    titles = Talk.GetTitles()
    return jsonify(titles)


@app.route("/talk/times/<title>", methods=["GET"])
def talktitletimes(title):
    token = session["token"]
    if token == "": abort(401)
    if not auth.checktoken(token): abort(401)

    times = Talk.GetTitleTimes(title)
    return jsonify(times)



if __name__ == '__main__':
    port = cfg.getint("server","port")
    
    app.run(
        host = '0.0.0.0',
        port = port,
        debug = False
    )