from flask import Flask, render_template, request, make_response, Response, redirect, jsonify
import json
from time import time
import sqlite3
from kafka import KafkaConsumer, TopicPartition
import psutil
import os
import subprocess
from threading import Thread
import cv2
import psutil
import zmq
import numpy as np
import configparser
import argparse
import subprocess as sp
UPLOAD_FOLDER = './static/uploads/'
app = Flask(__name__, static_url_path='/static')
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.secret_key = os.urandom(24)
try:
    conn = sqlite3.connect(
        '/usr/lib/python3.8/dist-packages/web/data.db', check_same_thread=False)
except:
    conn = sqlite3.connect(
        '/home/runner/work/project/project/web/web/data.db', check_same_thread=False)
curs = conn.cursor()
args = None
PORTS = None
KAFKA_IP=None
MQ_SOCKETS = []
# Обработка 404

@app.errorhandler(404)
def error(error):
    return render_template('error.html'), 404

# Домашняя страница
@app.route('/')
def main_():
    return render_template('index.html')


@app.route('/user', methods=["GET", "POST"])
def home():
    return render_template('index.html')


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


@app.route("/alldata")
def alldata():
    conn.row_factory = sqlite3.Row
    curs.execute("SELECT * FROM data ORDER BY timestamp DESC")
    rows = curs.fetchall()
    return render_template('alldata.html', rows=rows)


def streamer(camera, socket):
    import base64

    while True:
        obj = socket.recv_string()
        source_id = obj[:len(str(camera))]
        frame = obj[len(str(camera)):]
        if source_id == str(camera):
            img = base64.b64decode(frame)
            npimg = np.frombuffer(img, dtype=np.uint8)
            source = cv2.imdecode(npimg, 1)
            return cv2.imencode('.jpg', source)[1].tobytes(), source


def get_video_stream(cam):
    while True:
        stream = streamer(cam, MQ_SOCKETS[int(cam)])[0]
        yield (b'--frame\r\n'b'Content-Type: image/jpeg\r\n\r\n' + stream + b'\r\n\r\n')


@app.route("/cam/<camera>")
def cam(camera):
    return Response(get_video_stream(camera), mimetype='multipart/x-mixed-replace; boundary=frame')


@app.route("/cameras")
def get_cameras():
    return render_template("pattern.html", images=list(range(int(2))))

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


@app.route('/face', methods=['GET'])
def verify():
    return render_template("pattern.html", images=list(range(int(2))), service_name="Распознавание лиц", table="True")


@app.route('/env', methods=['POST', 'GET'])
def environment():
    return render_template('pattern.html', images=list(range(int(2))), service_name="Ситуационная обстановка", table="True", column_names=['Дата', 'Камера', 'Ситуация'],part="/kafka/env")

@app.route("/fire")
def fire_detect():
    return render_template("pattern.html", images=list(range(int(2))), service_name="Пожарная безопасность", table="True",part="/kafka/fire")


def get_gpu_memory():
    try:
        command = "nvidia-smi --query-gpu=memory.used --format=csv"
        memory_free_info = sp.check_output(
            command.split()).decode('ascii').split('\n')[:-1][1:]
        memory_free_values = [int(x.split()[0])
                            for i, x in enumerate(memory_free_info)]
    except:
            memory_free_values=[0,'nvidia-smi not installed']
    return memory_free_values


@app.route('/data', methods=["GET"])
def data():
    data = [time() * 1000, get_gpu_memory()[0],
            psutil.cpu_percent(), psutil.virtual_memory()[2]]
    response = make_response(json.dumps(data))
    response.content_type = 'application/json'
    return response


@app.route('/kafka/<ip_adress>/<topic>', methods=['GET'])
def read_kafka(topic,ip_adress):
    consumer = KafkaConsumer(
        bootstrap_servers=[ip_adress],
        auto_offset_reset='latest'
    )
    partitions = consumer.partitions_for_topic(topic)
    topic_partitions = [TopicPartition(topic, p) for p in partitions]
    consumer.assign(topic_partitions)
    last_messages = {}
    for tp in topic_partitions:
        last_offset = consumer.end_offsets([tp])[tp]
        if last_offset == 0:
            continue
        consumer.seek(tp, last_offset-1)
        msg = consumer.poll(timeout_ms=1000)
        for tp, msgs in msg.items():
            for msg in msgs:
                from datetime import datetime
                date = datetime.fromtimestamp(msg.timestamp/1000).strftime('%Y-%m-%d %H:%M:%S')  
                last_messages[tp.partition] = [str(date), msg.value.decode('utf-8')]
    response = make_response(json.loads(json.dumps(last_messages)))
    response.content_type = 'application/json'
    return response


class Listener(Thread):
    def __init__(self):
        Thread.__init__(self)
        self.active = True

    def run(self):
        subprocess.run(["../broker/core"])


def iniparser(str_ini, args):
    config = configparser.ConfigParser()
    config.read(str_ini)
    result = []
    if args.mode == "demo":
        for section in config.sections():
            if section.startswith('demofile_'):
                value = config.get(section, 'port')
                result.append(value)
    else:
        if args.mode == "real":
            for section in config.sections():
                if section.startswith('camera_'):
                    value = config.get(section, 'port')

                    result.append(int(value))
    return result


def main():
    parser = argparse.ArgumentParser(prog='VideoStreamer')
    parser.add_argument('mode')
    args = parser.parse_args()
    PORTS= iniparser('/usr/lib/python3.8/dist-packages/videoservice/cam_config.ini', args)
    print(PORTS)
    for i in range(len(PORTS)):
        context = zmq.Context()
        socket = context.socket(zmq.SUB)
        socket.setsockopt_string(zmq.SUBSCRIBE, "")
        socket.connect("tcp://127.0.0.1:"+str(PORTS[i]))
        MQ_SOCKETS.append(socket)

    app.run()


def for_test():
    return app
