# server.py
from flask import Flask, render_template, request
from flask_socketio import SocketIO
import numpy as np
import json

app = Flask(__name__)

socketio = SocketIO(app,
                    # async_mode='threading',
                    binary=True,
                    )


# https://github.com/astropy/astropy/issues/4604
def table_to_python(table):
    """Convert Astropy Table to Python dict.

    Numpy arrays are converted to lists, so that
    the output is JSON serialisable.

    Can work with multi-dimensional array columns,
    by representing them as list of list.
    """
    total_data = {}
    for name in table.colnames:
        data = table[name].tolist()
        total_data[name] = data
    return total_data


# https://gitlab.ut.ee/tonis.eenmae/poemsdb_raw/-/blob/7f3070ead0c0e9ba4f4a39143dc6118614379b2a/simbadquery.py
def query_simbad_coordinates(target):
    """Return data from Simbad database based on object name.  Using
    Simbad name query, retrieve object names, J2000 coordinates, and
    visual magnitude Input: object name Output: Simbad object name(s)
    with magnitudes, coordinates, proper motions and spectral class
    """
    from astroquery.simbad import Simbad
    
    customSimbad = Simbad()
    customSimbad.get_votable_fields()
    # See about formatting query results:
    # http://simbad.u-strasbg.fr/simbad/sim-help?Page=sim-fscript
    # When new fields are added, possibly database table structure has to be
    # reviewed, too.
    customSimbad.add_votable_fields('typed_id',
                                    'id(NAME)',
                                    'id(HD)',
                                     'id(HR)',
                                     'id(V*)',
                                     'id(HIP)',
                                     'id(TYC)',
                                     'id(GAIA)',
                                     'id(2MASS)',
                                     'flux(V)',
                                     'flux(B)',
                                     'flux(G)',
                                     'ra(:s;A;ICRS;2000.0;J2000)',
                                     'dec(:s;D;ICRS;2000.0;J2000)',
                                     'ra(d;A;ICRS;2000.0;J2000)',
                                     'dec(d;D;ICRS;2000.0;J2000)',
                                     'pmra',
                                     'pmdec',                                      
                                     'sp(S)')
    # customSimbad.remove_votable_fields('coordinates')
    try:
        result_table = customSimbad.query_object(target)
        if len(result_table.errors):
            print(f'Result_table errors: {result_table.errors}')
            # log.debug(f'Query for target {target} was successful')
        return result_table
    except Exception as e:
        print(e)


# Function to send the matrix to the client
def send_matrix():
    matrix = np.random.rand(3, 3).astype("uint8")
    binary_data = matrix.tobytes()
    socketio.emit(u'matrix', {"data": binary_data})    # object with binary stuff
    #socketio.emit(u'matrix', bytes({"data": [1,2,3]})) # normal "json" object

# Background thread to send the matrix every 5 seconds
def background_thread():
    while True:
        send_matrix()
        socketio.sleep(2)

    
# Route for the HTML page
@app.route('/')
def index():
    return render_template('index.html')

# Route for the HTML page
@app.route('/tel')
def tel():
    return render_template('tel.html')

# Route for the HTML page
@app.route('/simbad', methods=["POST"])
def simbad():
    req = request.json
    print(type(req))
    table = query_simbad_coordinates(req)
    print(table)
    res = table_to_python(table)
    return res

# Socket.IO event handlers
@socketio.on('connect')
def handle_connect():
    print('Client connected')

@socketio.on('disconnect')
def handle_disconnect():
    print('Client disconnected')

@socketio.on('message')
def handle_message(message):
    print('Received message:', message)

if __name__ == '__main__':

    # socketio.start_background_task(target=background_thread)
    
    # socketio.run(app, host="0.0.0.0", port=5002, debug=True)
    app.run(host="0.0.0.0", port=5002, debug=True)
