from flask import Flask, request, jsonify, render_template, session
import pymongo.synchronous
import pymongo.synchronous.cursor
import requests
from flask_socketio import SocketIO, join_room, leave_room
import json
import uuid
import pymongo
import copy
import datetime
from pprint import pprint

app = Flask(__name__)
app.secret_key = '11gs22h2h1a4h6ah8e413a45'
socketio = SocketIO(app)
users = {}
current_title = "Test Title"

def updateViewerCount(viewer_count):
    socketio.emit('updateViewerCount', viewer_count, to="stream")

import random

adjectives = ["Whispering", "Mystic", "Lively", "Cheerful"]
nouns = ["Phoenix", "Wizard", "Dream", "Voyager"]

def random_chatter_name():
    return f"{random.choice(adjectives)}{random.choice(nouns)}"

@socketio.on('join-notifications')
def join_notifications():
    channel = "notifications"
    join_room(channel)
    print(request.sid)
    socketio.emit('connect-notifications', to=request.sid)

@socketio.on('join')
def on_join():
    channel = "stream"
    myuuid = uuid.uuid4()
    print('joined!')

    session['uuid'] = str(myuuid)
    session['username'] = random_chatter_name()

    metadata = getStreamMetaData()
    metadata['viewer_count'] = metadata['viewer_count'] + 1
    updateStreamMetaData(metadata)

    updateViewerCount(metadata['viewer_count'])
    join_room(channel)

    socketio.emit('joined', {'channel': channel, 'uuid': str(myuuid), 'username': session['username']}, to=request.sid)

@socketio.on('connect')
def handle_connect():
    print('Client connected')

@socketio.on('disconnect')
def handle_disconnect():
    
    metadata = getStreamMetaData()
    metadata['viewer_count'] = metadata['viewer_count'] - 1
    updateStreamMetaData(metadata)
    updateViewerCount(metadata['viewer_count'])
    print(f"A user has left the treehouse,  starlit guests remain!")

@socketio.on('leave')
def on_leave(data):
    channel = "stream"
    global viewer_count
    viewer_count -= 1
    print(viewer_count)
    leave_room(channel)

@socketio.on('messageSend')
def handle_event(data):
    print('Received:', data)
    socketio.emit('messageReceive', data, to=data['channel_id'])

@socketio.on('notification')

async def titleChanged(title):
    socketio.emit('titleChanged', title, to="stream")

async def userJoined(user):
    socketio.emit('userJoined', user, to="stream")

async def userLeft(user):
    socketio.emit('userLeft', user, to="stream")

async def newMessage():
    socketio.emit('newMessage', to="stream")

async def userNameChanged(user):
    socketio.emit('userNameChanged', user, to="stream")

@app.route('/test')
def misskey_bridge():
    print('test')
    data = request.json
    print(data)
    return jsonify({"status": "success"}), 200


@app.route('/webhook', methods=['POST'])
async def webhook():
    data = request.json
    # Process the data and post it to Misskey
    await post_to_misskey(data)
    return jsonify({"status": "success"}), 200

@app.route('/stream', methods=['GET'])
def stream():
    metadata = getStreamMetaData()
    return render_template('stream.html', metadata=metadata)


def get_events():
    client = pymongo.MongoClient('mongodb://192.168.1.67:27017')
    db = client['gathio']

    collections = db.list_collection_names()
    print(collections)


    current_date = datetime.datetime.now()

    collection = db['events']

    events: pymongo.synchronous.cursor.Cursor = collection.find({'end': {'$gt': current_date}})

    if events.collection.estimated_document_count() > 0:
        return list(events)
    else:
        return []

def get_radios():
    response = requests.get("https://cast.treehousefullofstars.com/api/stations")
    return(response.json())

@app.route('/events', methods=['GET'])
def events():
    events = get_events()
    new_events = []
    for event in events:
        new_events.append(list(event.keys()))
        pprint(event)
        pprint(event['_id'])
    with open('events.json', 'w+') as file:
        json.dump(new_events, file, indent=5)

    return render_template('events.html', events=events)

@app.route('/misskey-connect', methods=['POST'])
def misskey_connect():
    if request.method == "POST":
        # print(request.get_json())
        data = request.get_json()
        if data['body']['type'] == "note":
            print(True)
            title = data['body']['body']['user']['name']
            body = data['body']['body']['text']
            print(title, body)
            sendGlobalNotification(title, body)
    return jsonify({})

def sendGlobalNotification(title, body):
    socketio.emit('send-notification', {"title": title, "body":body}, to="notifications")
    

def get_now_playing(shortcode):
    response = requests.get(f"https://cast.treehousefullofstars.com/api/nowplaying/{shortcode}")
    return response.json()

@app.route('/radios', methods=['GET'])
def radios():
    radios = get_radios()
    return render_template('radios.html', radios=radios)

@app.route('/getNotes', methods=['GET'])
def getNotes():
    if request.method == "GET":
        headers = {"Content-Type": "application/json"}
        local_timeline_api_endpoint = "https://misskey.treehousefullofstars.com/api/notes/local-timeline"
        payload = {"withFiles": False, "withRenotes": False, "withReplies": True, "limit": 50}
        response = requests.post(local_timeline_api_endpoint, headers=headers, json=payload)
        return jsonify({'notes': response.json()})
    

@app.route('/', methods=['GET'])
def home():
    radios = get_radios()
    events = get_events()
    metadata = getStreamMetaData()
    return render_template('home.html', events=events, radios=radios, stream=metadata)

def updateStreamMetaData(metadata):
    with open('stream.json', 'w+') as file:
        file.write(json.dumps(metadata, indent=5))

def getStreamMetaData():
    with open('stream.json', 'r+') as file:
        return json.load(file)

notify = True
async def post_to_misskey(data):
    access_token = "JSvVuz1eS2BGq6MagdQC9m109gOllwcO"
    misskey_server_url = "https://misskey.treehousefullofstars.com"
    api_endpoint = f"{misskey_server_url}/api/notes/create"

    print(data)
    global current_title
    if data['type'] == 'STREAM_STARTED':
        note_content = f"\n**{data['eventData']['name']}**\n'{data['eventData']['streamTitle']}' has just started streaming! Gather round!\nhttp://184.83.153.182:5000/stream #stream"
        current_title = data['eventData']['streamTitle']
        metadata = getStreamMetaData()
        metadata['last_known_title'] = current_title
        metadata['online'] = True
        updateStreamMetaData(metadata)
        sendGlobalNotification(current_title, note_content)
    elif data['type'] == 'STREAM_STOPPED':
        note_content = f"\n**{data['eventData']['name']}**\n'{data['eventData']['streamTitle']}' has finished! I hope you enjoyed and stick around to chat! #stream"
        metadata = getStreamMetaData()
        metadata['last_known_title'] = current_title
        metadata['online'] = False
        updateStreamMetaData(metadata)
    elif data['type'] == 'STREAM_TITLE_UPDATED':
        note_content = f"\n**{data['eventData']['name']}**\nNow streaming '{data['eventData']['streamTitle']}'! #stream"
        current_title = data['eventData']['streamTitle']
        await titleChanged(current_title)
        metadata = getStreamMetaData()
        metadata['last_known_title'] = current_title
        updateStreamMetaData(metadata)
    elif data['type'] == 'USER_PARTED':
        users[data['eventData']['id']] = data['eventData']
        await userJoined(data['eventData'])
    elif data['type'] == 'USER_PARTED':
        del users[data['eventData']['id']]
        await userLeft(data['eventData'])
    elif data['type'] == 'CHAT':
        await newMessage()
    elif data['type'] == 'NAME_CHANGE':
        users[data['eventData']['id']] = data['eventData']
        await userNameChanged(data['eventData'])

    
    if data['type'] == 'STREAM_STARTED' and notify or data['type'] == 'STREAM_STOPPED' and notify:
        print(note_content)
        payload = {
            "text": note_content
        }

        headers = {
            "Authorization": f"Bearer {access_token}",
            "Content-Type": "application/json"
        }   

        response = requests.post(api_endpoint, json=payload, headers=headers)

        # Check the response
        if response.status_code == 200:
            print("Note created successfully!")
        else:
            print(f"Failed to create note. Status code: {response.status_code}, Response: {response.text}")

    if data['type'] == 'STREAM_TITLE_UPDATED' and notify:
        print(note_content)
        payload = {
            "text": note_content
        }

        headers = {
            "Authorization": f"Bearer {access_token}",
            "Content-Type": "application/json"
        }   

        response = requests.post(api_endpoint, json=payload, headers=headers)

        # Check the response
        if response.status_code == 200:
            print("Note created successfully!")
        else:
            print(f"Failed to create note. Status code: {response.status_code}, Response: {response.text}")

if __name__ == '__main__':
    socketio.run(app, host="0.0.0.0", port=5000, debug=True)

#if __name__ == "__main__":
 #   app.run(host='0.0.0.0', port=5000, debug=True)