from qgis import processing
from qgis.processing import alg
from qgis.core import QgsProject, QgsGeometry, QgsPointXY, QgsFeature
from qgis.utils import iface
import json
import requests
import time

# (c) Morten Sickel, 2021-06-20
# Licenced under GPLv2

@alg(name='lynevent', label='Realtime events fra lyn.met.no',
     group='examplescripts', group_label='Example scripts')
# 'INPUT' is the recommended name for the main input parameter
@alg.input(type=alg.SOURCE, name='INPUT', label='Input vector layer')
# 'OUTPUT' is the recommended name for the main output parameter
@alg.output(type=alg.NUMBER, name='NUMBEROFFEATURES',
            label='Number of features processed')

def lynevent(instance, parameters, context, feedback, inputs):
    """
    This algorithm is to be run continously to fetch data from 
    https://lyn.met.no/events into a predefined data set. 
    """
    r = requests.get('https://lyn.met.no/events', stream=True)
    # This starts a continous retrieval of data
    layer = instance.parameterAsVectorLayer(parameters,'INPUT', context)
    # Makes the layer autorefresh each second
    layer.setAutoRefreshInterval(1000)
    # Enable auto refresh
    layer.setAutoRefreshEnabled(True)
    vpr = layer.dataProvider()
    if r.encoding is None:
        r.encoding = 'utf-8'
    n=0
    for line in r.iter_lines(decode_unicode=True):
        if line:
            j=None
            if line.startswith('data:'):
                (d,j)=line.split(' ')
            if not j is None:
                n+=1
                event=json.loads(j)
                # Timestamp for the event
                epoch=event[0]['Epoch']
                pnt = QgsGeometry.fromPointXY(QgsPointXY(event[0]['Point'][0],event[0]['Point'][1]))
                f = QgsFeature()
                f.setGeometry(pnt)
                f.setAttributes([None,epoch])
                # Enable next line to have the timestamp logged in the processing log
                # feedback.pushInfo(epoch)
                vpr.addFeatures([f])
        # This handles a click on the cancel button. One issue, it will not be 
        # cancelled until next event is processed        
        if feedback.isCanceled():
            feedback.pushInfo('{} events processed'.format(n))
            return {'NUMBEROFFEATURES': n}
    return {'NUMBEROFFEATURES': n}
