from flask import Flask, request, render_template, Response
from flask import make_response, jsonify
import sys
import os

import requests
import json
import threading
import time
import pandas as pd
import tempfile
import datetime
from collections import defaultdict
import namegenerator



sys.path.append(os.path.abspath("./"))
from apollo.Scraper.config import (
    USER_AGENT,
    YOUTUBE_VIDEO_URL,
)

if not(os.path.isdir(os.path.join('./', 'downloads'))):
    os.mkdir(os.path.join('./', 'downloads'))

from apollo.Scraper.LinkParser import extract_id
from apollo.inference.inference import inference_v2, load_model
from apollo.Scraper.download_comments import download_comments

app = Flask(__name__)
app.secret_key = os.urandom(24)
LOAD_MODEL_THREAD = None
chart_data = [0, 0]
log_data = ''
DATA_STORE = defaultdict(list)


COMMENTS_STORE = []

@app.after_request
def add_header(response):
    """
    Add headers to both force latest IE rendering engine or Chrome Frame,
    and also to cache the rendered page for 10 minutes.
    """
    response.headers["X-UA-Compatible"] = "IE=Edge,chrome=1"
    response.headers["Cache-Control"] = "public, max-age=0"
    return response


def scrapper_v2(youtube_id, sensitivity, limit):
    '''

    Code modified from : https://github.com/egbertbouman/youtube-comment-downloader
    :param youtube_id: ID of Youtube Video Link
    :param sensitivity: Sensitivity tolerance level (To be used as threshold during inference)
    :param limit: Number of comments to be scraped
    :return: CSV file of output comments
    '''
    try:
        # if LOAD_MODEL_THREAD is not None:
        LOAD_MODEL_THREAD.join()
        global chart_data
        global log_data
        global DATA_STORE
        
        filename = '{}_{}_{}.csv'.format(youtube_id, sensitivity, limit)

        chart_data = [0, 0]
        log_data = ''

        df = pd.DataFrame(columns=['id', 'comment', 'score', 'sensitivity'])
        toxic_count, nontoxic_count = 0 , 0
        count_list = []
        comment_list = []
        score_list = []
        sensitivity_list = []

        if not youtube_id:
            log_data = 'error'
            chart_data = [0, 0]
            raise ValueError("you need to specify a Youtube ID")

        print("Downloading Youtube comments for video:", youtube_id)

        count = 0
        session = requests.Session()
        session.headers["User-Agent"] = USER_AGENT
        response = session.get(YOUTUBE_VIDEO_URL.format(youtube_id=youtube_id))
        html = response.text
        if "og:title" in html:
            for comment in download_comments(youtube_id):
                comment_content = comment['content']
                score = inference_v2(comment_content, sensitivity)
                count += 1
                count_list.append(count)
                comment_list.append(comment_content)
                score_list.append(score)
                sensitivity_list.append(sensitivity)

                if score > (sensitivity):
                    toxic_count += 1
                else:
                    nontoxic_count +=1

                chart_data = [toxic_count, nontoxic_count]
                # comment['author']
                author_dummy_name = namegenerator.gen()
                extra_log_data = [comment['content'], comment['time'], author_dummy_name, comment['votes'], comment['photo'], str(score)]
                

                if limit and count >= limit:
                    DATA_STORE[youtube_id].append({'chart_data':chart_data, 'extra_log_data': extra_log_data, 'task_finished': True, 'success': True, 'index': count, 'filename': filename})
                    df['id'], df['comment'], df['score'], df['sensitivity'] = count_list, comment_list, score_list, sensitivity_list
                    LOG_RESULT_DATA = filename
#                     filepath = os.path.abspath(os.path.join('./', 'downloads', filename))
                    filepath = os.path.abspath(os.path.join('./apollo/Frontend/static', filename))
                    df.to_csv(filepath, encoding='utf-8')
                    break
                else:
                    DATA_STORE[youtube_id].append({'chart_data':chart_data, 'extra_log_data': extra_log_data, 'task_finished': False, 'success': True, 'index': count, 'filename': filename})

                print(comment_content, toxic_count, nontoxic_count, score)
                sys.stdout.write("Downloaded %d comment(s)\r" % count)
                sys.stdout.flush()
                
            print("\nDone!")

        else:
            print(f"The provided YouTube ID : {youtube_id} is invalid! ")
            DATA_STORE[youtube_id].append({'chart_data':[], 'extra_log_data': [], 'task_finished': True, 'success': False, 'index': -1, 'filename': ''})
            log_data = 'error'
            chart_data = [0, 0]

    except Exception as e:
        print("Error:", str(e))
        sys.exit(1)



@app.route('/chart-data', methods=['GET'])
def chart_data():
    if request.method == 'GET':
        url = request.args.get('url')
        youtube_id = extract_id(url)

    def send_data(youtube_id):
        while len(DATA_STORE[youtube_id])>0:
            json_data = json.dumps(DATA_STORE[youtube_id].pop(0))
            yield f"data:{json_data}\n\n"
            time.sleep(1)

    return Response(send_data(youtube_id), mimetype='text/event-stream')


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


@app.route("/index.html")
def home_index():
    response = make_response(render_template("index.html"))
    response = add_header(response)
    return response


@app.route("/")
def home():
    global LOAD_MODEL_THREAD
    LOAD_MODEL_THREAD = threading.Thread(target=load_model, args=())
    LOAD_MODEL_THREAD.daemon = True
    LOAD_MODEL_THREAD.start()

    response = make_response(render_template("index.html"))
    response = add_header(response)
    return response



@app.route('/predict',methods=['GET', 'POST'])
def predict():
    print('STARTING PREDICTION*********************')
    '''
    For rendering results on HTML GUI
    '''
    global COMPLETED
    global LIMIT

    COMPLETED = False
    COMMENT_URL = [x for x in request.form.values()]
    if len(COMMENT_URL[0]) == 0:
        return jsonify(msg='URL missing', status='error')
    
    COMMENT_LINK = extract_id(COMMENT_URL[0])
    SENSITIVITY = float(COMMENT_URL[1])
    LIMIT = int(COMMENT_URL[2])
    if COMMENT_LINK is None:
        print("Invalid link or the link is not supported yet.")
        '''
        Add a function to show the error message in html page
        '''
        return render_template('index.html',name ='')

    else:
        print (COMMENT_LINK)
    
    scrapper_v2(COMMENT_LINK, SENSITIVITY, LIMIT)
    
    return jsonify(msg='scraping successfully', status='success')



if __name__ == "__main__":
    app.run(debug=True, threaded=True)
