# 主業務邏輯中的視圖和路由的定義
import os
import datetime
from flask import render_template, request, session, Response
# 導入藍圖程序，用於構建路由
from werkzeug.utils import redirect
from . import main
from manage import mqtt
# 導入db，用於操作數據庫
from manage import db
# 導入實體類，用於操作數據庫
from ..models import *
import json
from datetime import datetime as dt
from sqlalchemy import text
import socket
import pickle
import cv2
import numpy as np
import math
import threading
import time
from flask_mqtt import Mqtt


c_sock = 0
s_sock = 0



# 主頁的訪問路徑
@main.route('/')
def main_index():
    # 獲取登入信息
    if 'id' in session and 'uname' in session:
        return render_template('allindex.html')
    else:
        return render_template('sign_in.html')


# 登入頁面的訪問路徑
@main.route('/login', methods=['GET', 'POST'])
def login_views():
    if request.method == 'GET':
        if 'id' in session and 'uname' in session:
            return redirect('/')
        else:
            return render_template('sign_in.html')
    else:
        # 接收前端傳過來的資料
        username = request.form['username']
        password = request.form['password']
        # 使用接收的用戶和密碼到資料庫中查詢
        user = User.query.filter_by(account=username, password=password).first()
        # 如果用戶存在，將信息保存置session並重定向回首頁，否則重定向回登入頁
        if user:
            resp = redirect('/')
            # 判斷是否有記住密碼
            if 'rem' in request.form:
                sn = str(user.sn)
                max_age = 60 * 60 * 24 * 365
                resp.set_cookie("username", username, max_age=max_age)
                resp.set_cookie("sn", sn, max_age=max_age)

            session['uname'] = user.account
            session['id'] = user.sn
            return resp
        else:
            errMsg = "Wrong login or password"
            return render_template('sign_in.html', errMsg=errMsg)


# 註冊頁面的訪問路徑
@main.route('/register', methods=['POST', "GET"])
def register_views():
    if request.method == 'GET':
        return render_template('registration.html')
    else:
        # 獲取文本框的值並賦值給user實體對象
        user = User()
        user.account = request.form['username']
        user.password = request.form['password']
        # 將數據保存進資料庫  - 註冊
        db.session.add(user)
        # 手動提交，目的是為了獲取提交後的user的id
        db.session.commit()
        # 當user成功插入進資料庫之後，程序會自動將所有信息取出來在賦值給user
        # 完成登入的操作
        user = User.query.filter_by(account=user.account).first()
        session['id'] = user.sn
        session['uname'] = user.account
        return redirect('/')


# 毛豆田的主頁面
@main.route('/aindex', methods=['POST', 'GET'])
def aindex_views():
    return render_template('aindex.html')


# 毛豆車的主頁面
@main.route('/cindex', methods=['POST', 'GET'])
def cindex_views():
    return render_template('cindex.html')


# 毛豆田拍攝設定的主頁面
@main.route('/ashoot_setting/<tid>', methods=['POST', 'GET'])
def ashoot_setting_views(tid):
    if request.method == 'GET':
        global s_sock, c_sock
        #當跳轉小兵頁面時，判定scoket是否還在連接中
        if c_sock != 0:
            c_sock.shutdown(2)
            c_sock.close()
            c_sock = 0
            print("c_sock is closing")
        if s_sock != 0:
            s_sock.shutdown(2)
            s_sock.close()
            s_sock = 0
            print("s_sock is closing")

        dict = request.args.to_dict()
        if dict:
            try:
                nr = "KDAIS" + dict['nr']
                mode = int(dict['mode'])
                jvtotime = JvtOTime.query.filter_by(nr=nr, MODE=mode).order_by(text('datetime desc')).first()
                tilt_angle = jvtotime.tilt_angle
                pan_angle = jvtotime.pan_angle
                zoom = str(jvtotime.zoom_now)
                time1 = jvtotime.time1
                time2 = jvtotime.time2
                time3 = jvtotime.time3
                time4 = jvtotime.time4
                time5 = jvtotime.time5
                time6 = jvtotime.time6
                time7 = jvtotime.time7
                time8 = jvtotime.time8
                dict = {"tilt_angle": tilt_angle, "pan_angle": pan_angle, "zoom": zoom, "time1": time1,
                        "time2": time2, "time3": time3, "time4": time4, "time5": time5, "time6": time6,
                        "time7": time7, "time8": time8}
                return json.dumps(dict)
            except Exception:
                dict = {"tilt_angle": "0", "pan_angle": "0", "zoom": "0", "time1": "00000000",
                        "time2": "00000000", "time3": "00000000", "time4": "00000000", "time5": "00000000",
                        "time6": "00000000",
                        "time7": "00000000", "time8": "00000000"}
                return json.dumps(dict)

        return render_template('aim.html', params=locals())
    else:
        dict = request.form.to_dict()
        jvtotime = JvtOTime()
        if dict['nr'] == '1':
            jvtotime.MAC = 'b8:27:eb:a1:b0:70'
        elif dict['nr'] == '2':
            jvtotime.MAC = 'b8:27:eb:e7:51:44'
        elif dict['nr'] == '3':
            jvtotime.MAC = 'b8:27:eb:ce:a5:35'
        elif dict['nr'] == '4':
            jvtotime.MAC = 'b8:27:eb:06:9a:f1'
        elif dict['nr'] == '5':
            jvtotime.MAC = 'b8:27:eb:0c:f0:21'
        elif dict['nr'] == '6':
            jvtotime.MAC = 'b8:27:eb:df:4b:0f'
        elif dict['nr'] == '7':
            jvtotime.MAC = 'b8:27:eb:af:df:b6'
        elif dict['nr'] == '8':
            jvtotime.MAC = 'b8:27:eb:d2:d0:8f'
        elif dict['nr'] == '9':
            jvtotime.MAC = 'b8:27:eb:57:3c:da'
        elif dict['nr'] == '10':
            jvtotime.MAC = 'b8:27:eb:bd:29:b1'
        elif dict['nr'] == '11':
            jvtotime.MAC = 'b8:27:eb:7c:f6:06'
        elif dict['nr'] == '12':
            jvtotime.MAC = 'b8:27:eb:74:bd:ac'
        elif dict['nr'] == '13':
            jvtotime.MAC = 'b8:27:eb:e7:21:e5'
        elif dict['nr'] == '14':
            jvtotime.MAC = 'b8:27:eb:6f:5a:6b'
        elif dict['nr'] == '15':
            jvtotime.MAC = 'b8:27:eb:e3:f1:f4'
        elif dict['nr'] == '16':
            jvtotime.MAC = 'b8:27:eb:60:1c:2e'
        elif dict['nr'] == '17':
            jvtotime.MAC = 'b8:27:eb:9d:68:05'
        elif dict['nr'] == '18':
            jvtotime.MAC = 'b8:27:eb:4d:e4:34'

        jvtotime.nr = 'KDAIS' + dict['nr']
        jvtotime.MODE = int(dict['mode'])
        jvtotime.tilt_angle = dict['tilt_angle']
        jvtotime.pan_angle = dict['pan_angle']
        jvtotime.zoom_before = 0
        jvtotime.zoom_now = int(dict['zoom'])
        jvtotime.time1 = dict['time1']
        jvtotime.time2 = dict['time2']
        jvtotime.time3 = dict['time3']
        jvtotime.time4 = dict['time4']
        jvtotime.time5 = dict['time5']
        jvtotime.time6 = dict['time6']
        jvtotime.time7 = dict['time7']
        jvtotime.time8 = dict['time8']
        jvtotime.datetime = dt.now()
        db.session.add(jvtotime)
        db.session.commit()

        return {"status": "OK"}


# 毛豆田歷史資料的主頁面
@main.route('/aimg_history/<tid>', methods=['POST', 'GET'])
def aimg_history_views(tid):
    if request.method == 'GET':
        return render_template('ahistory_ndvi1.html', params=locals())
    else:
        pass


# 毛豆車拍攝設定的主頁面
@main.route('/cshoot_setting/<tid>', methods=['POST', 'GET'])
def cshoot_setting_views(tid):
    if request.method == 'GET':
        return render_template('cim.html', params=locals())
    else:
        pass


# 毛豆車歷史資料的主頁面
@main.route('/cimg_history/<tid>', methods=['POST', 'GET'])
def cimg_history_views(tid):
    if request.method == 'GET':
        return render_template('chistory_ndvi1.html', params=locals())
    else:
        pass


# 退出的訪問路徑
@main.route('/logout')
def logout_views():
    if 'id' in session and 'uname' in session:
        del session['id']
        del session['uname']
    return redirect('/')




@main.route("/udp_client", methods=['POST', 'GET'])
def udp_views():
    time.sleep(0.5)
    if request.method == 'GET':
        def close():
            global c_sock
            time.sleep(300)
            c_sock.shutdown(2)
            c_sock.close()
            c_sock = 0
            print("c_sock is closing")

        max_length = 65000
        # max_length = 95000
        # lab1的IP
        # host = "192.168.50.65"
        # lab2的IP
        host = "192.168.51.161"
        port = 8000
        global c_sock
        c_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)


        t = threading.Thread(target=close)
        t.daemon = True
        t.start()

        # 地下室小兵
        cap = cv2.VideoCapture('rtsp://admin:abcd1234@192.168.51.48/av2_0')
        # 主機攝像頭
        # cap = cv2.VideoCapture(0)
        # 外面小兵
        # cap = cv2.VideoCapture('rtsp://admin:admin@192.168.50.182/av2_0')
        ret, frame = cap.read()

        while ret:
            # compress frame
            frame = cv2.resize(frame, (550, 400), interpolation=cv2.INTER_AREA)
            retval, buffer = cv2.imencode(".jpg", frame)


            if retval:
                # convert to byte array
                buffer = buffer.tobytes()
                # get size of the frame
                buffer_size = len(buffer)

                num_of_packs = 1
                if buffer_size > max_length:
                    num_of_packs = math.ceil(buffer_size / max_length)

                frame_info = {"packs": num_of_packs}

                # send the number of packs to be expected
                # print("Number of packs:", num_of_packs)
                c_sock.sendto(pickle.dumps(frame_info), (host, port))

                left = 0
                right = max_length

                for i in range(num_of_packs):
                    # print("left:", left)
                    # print("right:", right)

                    # truncate data to send
                    data = buffer[left:right]
                    left = right
                    right += max_length

                    # send the frames accordingly
                    c_sock.sendto(data, (host, port))

            ret, frame = cap.read()

        print("done")
    else:
        global c_sock
        c_sock.shutdown(2)
        c_sock.close()
        c_sock = 0
        print("c_sock is closing")




# 影像串流的路徑
@main.route("/video_feed", methods=['POST', 'GET'])
def video_feed_views():
    if request.method == 'GET':

        def close():
            global s_sock
            time.sleep(300)
            s_sock.shutdown(2)
            s_sock.close()
            s_sock = 0
            print("s_sock is closing")

        # lab1的IP
        # host = "192.168.50.65"
        # lab2的IP
        host = "192.168.51.161"
        port = 8000
        max_length = 65540
        # max_length = 95540
        print(host,port)

        global s_sock
        s_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        s_sock.bind((host, port))

        t = threading.Thread(target=close)
        t.daemon = True
        t.start()

        frame_info = None
        buffer = None
        frame = None


        print("-> waiting for connection")


        # 影像生成器函數，將影像以jpg格式傳給前端
        def generate():
            while True:
                global s_sock, frame_info, buffer, frame
                data, address = s_sock.recvfrom(max_length)

                if len(data) < 100:
                    frame_info = pickle.loads(data)


                    if frame_info:
                        nums_of_packs = frame_info["packs"]


                        for i in range(nums_of_packs):
                            data, address = s_sock.recvfrom(max_length)

                            if i == 0:
                                buffer = data
                            else:
                                buffer += data

                        frame = np.frombuffer(buffer, dtype=np.uint8)
                        frame = frame.reshape(frame.shape[0], 1)

                        frame = cv2.imdecode(frame, cv2.IMREAD_COLOR)
                        frame = cv2.resize(frame, (1280, 720), interpolation=cv2.INTER_AREA)

                        # encode the frame in JPEG format
                        (flag, encodedImage) = cv2.imencode(".jpg", frame)
                        # ensure the frame was successfully encoded
                        if not flag:
                            continue
                # yield the output frame in the byte format
                yield (b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' +
                    bytearray(encodedImage) + b'\r\n')

        # return the response generated along with the specific media
        # type (mime type)
        return Response(generate(), mimetype="multipart/x-mixed-replace; boundary=frame")
    else:
        global s_sock
        s_sock.shutdown(2)
        s_sock.close()
        s_sock = 0
        print("s_sock is closing")



#mqtt發布
@main.route('/mqtt', methods=['GET','POST'])
def mqtt_views():
    import json
    dict = request.args.to_dict()
    json = json.dumps(dict)
    print(json)
    mqtt.publish('AISKY/AppleFarm/MK-G/b8:27:eb:f8:24:92', json)
    return "Publish done"