"""

Author: Obrtac Tomas (obrtac.tomas@gmail.com)

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.

"""

import pycurl
from StringIO import StringIO
import json
from PySide.QtCore import QTime
import numpy as np
from datetime import datetime,timedelta
import re
from PySide import QtGui

Server = "147.229.46.137"

#Tato kniznica je vytvorena pre obsluhovanie REST api, viac info https://github.com/gotthardp/lorawan-server/blob/master/doc/Administration.md
#pod kolnkou REST API
#V skratke GET je na ziskavanie, PUT ma upravovanie a post na zakladanie
#Overujeme prihlasenie na server
def user_verification(password,name):
    try:
        buffer = StringIO()
        c = pycurl.Curl()
        url = ("http://%s:8080/users/" %Server) + name #Ak uzivatel existuje, prikaz sa vykona
        c.setopt(c.URL, url)
        c.setopt(pycurl.USERPWD, '%s:%s' % (name, password))
        c.setopt(c.WRITEDATA, buffer)
        c.perform()
        c.close()
        body = buffer.getvalue()
        if body != "" :
            return 1  #Prihlasenie bolo uspesne
        else:
            return 2 #Prihlasenie bolo neuspesne
    except :
        return 3 #Nepodarilo sa pripojit na server

#Zoznam Devaddr
def list_of_devaddr(password,name):
    buffer = StringIO()
    c = pycurl.Curl()
    c.setopt(c.URL, 'http://%s:8080/links' %Server)
    c.setopt(pycurl.USERPWD, '%s:%s' % (password,name))
    c.setopt(c.WRITEDATA, buffer)
    c.perform()
    c.close()
    body = buffer.getvalue()
    addreses = []
    number = 1
    #Parcovanie dat
    while (body.find("devaddr", number + 1) != -1): #Overovanie ci to je HEX
        number = body.find("devaddr", number + 1)
        adr = body[number + 10:number + 18]
        if re.sub(r'[^a-zA-Z0-9 ]', ' ', adr) == adr:
            addreses.append(adr)
    return addreses
# Zoznam DevEUI
def list_of_devEUI(password,name):
    buffer = StringIO()
    c = pycurl.Curl()
    c.setopt(c.URL, 'http://%s:8080/devices' %Server)
    c.setopt(pycurl.USERPWD, '%s:%s' % (password,name))
    c.setopt(c.WRITEDATA, buffer)
    c.perform()
    c.close()
    body = buffer.getvalue()
    addreses = []
    number = 1 #Aby nam to zacalo hladat od prvej hodnoty
    #Parcovanie dat
    while (body.find("deveui", number + 1) != -1):
        number = body.find("deveui", number + 1)
        adr = body[number + 9:number + 25]
        if re.sub(r'[^a-zA-Z0-9 ]', ' ', adr) == adr: #Overovanie ci to je HEX
            addreses.append(adr)
        #addreses.append(body[number + 9:number + 25])
    return addreses
#Zoznam s gatewaymi
def list_of_gateways(password,name):
    buffer = StringIO()
    c = pycurl.Curl()
    c.setopt(c.URL, 'http://%s:8080/gateways' %Server)
    c.setopt(pycurl.USERPWD, '%s:%s' % (password,name))
    c.setopt(c.WRITEDATA, buffer)
    c.perform()
    c.close()
    body = buffer.getvalue()
    addreses = []
    number = 1
    #Parcovanie dat
    while (body.find("mac", number + 1) != -1):
        number = body.find("mac", number + 1)
        adr = body[number + 6:number + 22]
        if re.sub(r'[^a-zA-Z0-9 ]', ' ', adr) == adr: #Overovanie ci to je HEX
            addreses.append(adr)
        #addreses.append(body[number + 9:number + 25])
    return addreses
#Ziskavanie dat od jednotlivych zariadeni
def read_data(devaddr,password,name):
    buffer = StringIO()
    c = pycurl.Curl()
    #Hodnoty zobrazujeme podla datumu pridania a to vzostupne. viac info https://github.com/marmelab/ng-admin/blob/master/doc/API-mapping.md
    url = ('http://%s:8080/rxframes' %Server) +'?_filters={%22devaddr%22:%22'  + devaddr + '%22}&_sortField=datetime&_sortDir=DESC'
    c.setopt(c.URL,url)
    c.setopt(pycurl.USERPWD, '%s:%s' % (password,name))
    c.setopt(c.WRITEDATA, buffer)
    c.perform()
    c.close()
    body = buffer.getvalue()
    number = 1
    link_values = data(devaddr)
    i = 0
    prev_datetime = ""
    actual_datime = ""
    #Postupne parcovanie dat
    while (body.find("datetime", number + 1) != -1):
        number = body.find("datetime", number + 1)
        date = body[number + 11:number + 30]
        date = date.split("T")
        actual_datime = date[0]
        number = body.find("data", number + 1)
        value = body[number + 7:body.find(",", number + 1) - 1]
        if actual_datime != prev_datetime:
            if prev_datetime != "":
                i += 1
                link_values.data_p.append([])
                link_values.data_t.append([])
                link_values.data_h.append([])
                link_values.data_l.append([])
                link_values.hour.append([])
            link_values.datetime.append(actual_datime)
        if len(value) == 20:
            link_values.data_t[i].append((float(int(value[0:4],16))/100)-50)
            link_values.data_h[i].append(float(int(value[4:8],16))/100)
            link_values.data_p[i].append(int(value[8:14],16))
            link_values.data_l[i].append(float(int(value[14:20],16))/100)
            link_values.hour[i].append(datetime.strptime(date[1], '%H:%M:%S') + timedelta(hours = 2))
            print value[12:16]
        prev_datetime = actual_datime
    return link_values

#Ziskavanie parametrov devicu
def parameters_of_device(deveui,password,name):
    Parameters = device(deveui)
    buffer = StringIO()
    c = pycurl.Curl()
    url = 'http://%s/devices/%s' %(Server ,deveui)
    c.setopt(c.URL, url)
    c.setopt(pycurl.USERPWD, '%s:%s' % (password,name))
    c.setopt(c.WRITEDATA, buffer)
    c.perform()
    c.close()
    body = buffer.getvalue()
    #Opat parcovanie a overovanie platnosti jednotlivych znakov
    position = body.find("link")
    if position != -1:
        Parameters.link = body[position+7:position+15]
    position = body.find("power")
    Parameters.power = body[position + 7]
    position = body.find("datr")
    Parameters.datr = body[position + 6]
    position = body.find("appkey")
    Parameters.appkey = body[position + 9:position + 41]
    position = body.find("appeui")
    Parameters.appeui = body[position + 9:position + 25]
    position = body.find("chans")
    Parameters.chans = body[position+8:body.find("}",position)-1]
    body = body.split(",")
    for i in range(len(body)):
        if body[i].find("can_join") != -1:
            Parameters.can_join = body[i][11:]
            break
    for i in range(len(body)):
        if body[i].find("app") == 1:
            if body[i][4].isalpha() == 0:
                Parameters.app = body[i][7:-1]
                break

    for i in range(len(body)):
        if body[i].find("region") != -1:
            Parameters.region = body[i][9:]
            break
    return Parameters

#Ziskavame hodnoty Linkov
def parameters_of_link(devaddr,password,name):
    Parameters = link(devaddr)
    buffer = StringIO()
    c = pycurl.Curl()
    url = 'http://%s:8080/links/%s' %(Server,devaddr)
    c.setopt(c.URL, url)
    c.setopt(pycurl.USERPWD, '%s:%s' % (password,name))
    c.setopt(c.WRITEDATA, buffer)
    c.perform()
    c.close()
    #Parcovanie a overovanie dat
    body = buffer.getvalue()
    if body == "":
        return -1
    position = body.find("power")
    Parameters.power = body[position + 7]
    if not Parameters.power.isdigit():
        Parameters.power = 0
    position = body.find("datr")
    Parameters.datr = body[position + 6]
    if Parameters.datr == "n":
        Parameters.datr = 0
    position = body.find("fcnt_check")
    Parameters.fcnt_check = body[position + 12]
    position = body.find("appskey")
    value = body[position + 10:position + 42]
    if re.sub(r'[^a-zA-Z0-9 ]', ' ', value) == value:
        Parameters.appskey = body[position + 10:position + 42]
    position = body.find("nwkskey")
    value = body[position + 10:position + 42]
    if re.sub(r'[^a-zA-Z0-9 ]', ' ', value) == value:
        Parameters.nwkskey = body[position + 10:position + 42]
    position = body.find("chans")
    Parameters.chans = body[position + 8:body.find("}", position) - 1]
    if Parameters.chans == "ul":
        Parameters.chans = None
    body = body.split(",")
    for i in range(len(body)):
        if body[i].find("app") == 1:
            if body[i][4].isalpha() == 0:
                Parameters.app = body[i][7:-1]
                break

    for i in range(len(body)):
        if body[i].find("region") != -1:
            Parameters.region = body[i][9:]
            break
    return Parameters
#Ziskavanie paratetrov gatewayii
def parameters_of_gateway(Mac,password,name):
    Parameters = gateway(Mac)
    buffer = StringIO()
    c = pycurl.Curl()
    url = 'http://%s:8080/gateways/%s' %(Server , Mac)
    c.setopt(c.URL, url)
    c.setopt(pycurl.USERPWD, '%s:%s' % (password,name))
    c.setopt(c.WRITEDATA, buffer)
    c.perform()
    c.close()
    body = buffer.getvalue()
    position = body.find("tx_rfch")
    Parameters.tx_rfch = body[position + 10]
    position = body.find("netid")
    value = body[position + 8:position + 14]
    if re.sub(r'[^a-zA-Z0-9 ]', ' ', value) == value:
        Parameters.netid = body[position + 8:position + 14]
    return Parameters

# Vytvorenie novej gatewaye
def create_new_gateway(Mac,Tx_c,netID,password,name):
    if len(re.sub(r'[^a-zA-Z0-9 ]', ' ', netID)) != 6:
        Wrong_input_parameters_message()
        return
    if len(re.sub(r'[^a-zA-Z0-9 ]', ' ', Mac)) != 16:
        Wrong_input_parameters_message()
        return
    c = pycurl.Curl()
    c.setopt(pycurl.POST, 1)
    c.setopt(c.URL, 'http://%s:8080/gateways' %Server)
    c.setopt(pycurl.USERPWD, '%s:%s' % (password,name))
    data = json.dumps(
        {"gpspos": {"lat": 48.88, "lon": 14.12}, "netid": "%s" %netID, "tx_rfch": "%s" %Tx_c, "mac": "%s" %Mac})
    c.setopt(pycurl.POSTFIELDS, data)
    c.setopt(pycurl.HTTPHEADER, ["Content-Type:application/json"])
    c.perform()
    c.close()
    QtGui.QMessageBox.question(None, "Message", "Gateway was created", QtGui.QMessageBox.Ok)

#Vytvaranie novej gatewaye
def create_new_link(Chanels,power,appskey,nwkskey,app,region,devaddr,fcnt_check,data_rate,password,name):
    if len(re.sub(r'[^a-zA-Z0-9 ]', ' ', appskey)) != 32:
        Wrong_input_parameters_message()
        return 0
    if len(re.sub(r'[^a-zA-Z0-9 ]', ' ', nwkskey)) != 32:
        Wrong_input_parameters_message()
        return 0
    if len(re.sub(r'[^a-zA-Z0-9 ]', ' ', devaddr)) != 8:
        Wrong_input_parameters_message()
        return 0
    region = region.replace(" ","")
    region = region[:-3]
    c = pycurl.Curl()
    c.setopt(pycurl.POST, 1)
    c.setopt(c.URL, ('http://%s:8080/links' %Server))
    c.setopt(pycurl.USERPWD, '%s:%s' % (password,name))
    data = json.dumps(
        {"devstat": {"battery": None, "margin": None}, "adr_set": {"power":power, "datr":data_rate, "chans": "%s" %Chanels},
         "adr_use": {"power":power,
                     "datr": "undefined", "chans": None}, "adr_flag_set": 1, "adr_flag_use": 0, "fcnt_check":fcnt_check,
         "last_rx": "2017-02-20T00:24:31Z", "fcntdown": 0, "fcntup": 0, "appskey": "%s" %appskey,
         "nwkskey": "%s" %nwkskey, "app": "%s" %app, "region": "%s" %region,
         "devaddr": "%s" % devaddr})
    c.setopt(pycurl.POSTFIELDS, data)
    c.setopt(pycurl.HTTPHEADER, ["Content-Type:application/json"])
    c.perform()
    c.close()
    QtGui.QMessageBox.question(None, "Message", "Link was created", QtGui.QMessageBox.Ok)
    return 1

#Vytvaranie noveho zariadenia
def create_new_device(Chanels,power,canjoin,appkey,appeui,app,region,deveui,data_rate,password,name):
    if len(re.sub(r'[^a-zA-Z0-9 ]', ' ', appkey)) != 32:
        Wrong_input_parameters_message()
        return
    if len(re.sub(r'[^a-zA-Z0-9 ]', ' ', appeui)) != 16:
        Wrong_input_parameters_message()
        return
    if len(re.sub(r'[^a-zA-Z0-9 ]', ' ', deveui)) != 16:
        Wrong_input_parameters_message()
        return
    region = region.replace(" ", "")
    region = region[:-3]
    c = pycurl.Curl()
    c.setopt(pycurl.POST, 1)
    c.setopt(c.URL, 'http://%s:8080/devices' %Server)
    c.setopt(pycurl.USERPWD, '%s:%s' % (password,name))
    data = json.dumps(
        {"adr_set": {"power": power, "datr": 1, "chans": "%s" %Chanels}, "adr_flag_set": 1, "fcnt_check":data_rate, "can_join": canjoin,
         "appkey": "%s" %appkey, "appeui": "%s" %appeui, "app": "%s" %app,
         "region": "%s" %region, "deveui": "%s" %deveui})
    c.setopt(pycurl.POSTFIELDS, data)
    c.setopt(pycurl.HTTPHEADER, ["Content-Type:application/json"])
    c.perform()
    c.close()
    QtGui.QMessageBox.question(None, "Message", "Device was created", QtGui.QMessageBox.Ok)

#Editovaine uz existujuceho linku
def edit_existing_link(Chanels,power,appskey,nwkskey,app,region,devaddr,fcnt_check,data_rate,password,name):
    if len(re.sub(r'[^a-zA-Z0-9 ]', ' ', appskey)) != 32:
        Wrong_input_parameters_message()
        return
    if len(re.sub(r'[^a-zA-Z0-9 ]', ' ', nwkskey)) != 32:
        Wrong_input_parameters_message()
        return
    if len(re.sub(r'[^a-zA-Z0-9 ]', ' ', devaddr)) != 8:
        Wrong_input_parameters_message()
        return
    region = region.replace(" ", "")
    region = region[:-3]
    c = pycurl.Curl()
    c.setopt(pycurl.CUSTOMREQUEST, "PUT")
    c.setopt(c.URL, 'http://%s:8080/links/%s' %(Server ,devaddr))
    c.setopt(pycurl.USERPWD, '%s:%s' % (password,name))
    data = json.dumps(
        {"devstat": {"battery": None, "margin": None}, "adr_set": {"power":power, "datr":data_rate, "chans": "%s" %Chanels},
         "adr_use": {"power":power,
                     "datr": "undefined", "chans": None}, "adr_flag_set": 1, "adr_flag_use": 0, "fcnt_check":fcnt_check,
         "last_rx": "2017-02-20T00:24:31Z", "fcntdown": 0, "fcntup": 0, "appskey": "%s" %appskey,
         "nwkskey": "%s" %nwkskey, "app": "%s" %app, "region": "%s" %region,
         "devaddr": "%s" % devaddr})
    c.setopt(pycurl.POSTFIELDS, data)
    c.setopt(pycurl.HTTPHEADER, ["Content-Type:application/json"])
    c.perform()
    c.close()
    QtGui.QMessageBox.question(None, "Message", "Link was modified", QtGui.QMessageBox.Ok)

#Editovaine uz existujuceho zariadenia
def edit_existing_device(Chanels,power,canjoin,appkey,appeui,app,region,deveui,data_rate,password,name):
    if len(re.sub(r'[^a-zA-Z0-9 ]', ' ', appkey)) != 32:
        Wrong_input_parameters_message()
        return
    if len(re.sub(r'[^a-zA-Z0-9 ]', ' ', appeui)) != 16:
        Wrong_input_parameters_message()
        return
    if len(re.sub(r'[^a-zA-Z0-9 ]', ' ', deveui)) != 16:
        Wrong_input_parameters_message()
        return
    #Opat ak su zadane chybne parametry tak je editacia vypnuta
    region = region.replace(" ", "")
    region = region[:-3]
    c = pycurl.Curl()
    c.setopt(pycurl.CUSTOMREQUEST, "PUT")
    url = 'http://%s:8080/devices/%s' %(Server ,deveui)
    c.setopt(c.URL, url)
    c.setopt(pycurl.USERPWD, '%s:%s' % (password,name))
    data = json.dumps(
        {"adr_set": {"power": power, "datr":data_rate, "chans": "%s" %Chanels}, "adr_flag_set": 1, "fcnt_check": 0, "can_join": canjoin,
         "appkey": "%s" %appkey, "appeui": "%s" %appeui, "app": "%s" %app,
         "region": "%s" %region, "deveui": "%s" %deveui})
    c.setopt(pycurl.POSTFIELDS, data)
    c.setopt(pycurl.HTTPHEADER, ["Content-Type:application/json"])
    c.perform()
    c.close()
    QtGui.QMessageBox.question(None, "Message", "Device was modified", QtGui.QMessageBox.Ok) #Ak je vsetko v pohode uspesna hlaska

#Editovanie existujucej gatewaye
def edit_existing_gateway(MAC,NetID,TXchanel,password,name):
    if len(re.sub(r'[^a-zA-Z0-9 ]', ' ', NetID)) != 6:
        Wrong_input_parameters_message()
        return
    if len(re.sub(r'[^a-zA-Z0-9 ]', ' ', MAC)) != 16:
        Wrong_input_parameters_message()
        return #Ak je neuspesne tak editacia je vypnuta
    c = pycurl.Curl()
    c.setopt(pycurl.CUSTOMREQUEST, "PUT")
    url = 'http://%s:8080/gateways/%s'  %(Server , MAC)
    c.setopt(c.URL, url)
    c.setopt(pycurl.USERPWD, '%s:%s' % (password,name))
    data = json.dumps(
        {"gpspos": {"lat": 48.88, "lon": 14.12}, "netid": "%s" % NetID, "tx_rfch": "%s" % TXchanel, "mac": "%s" % MAC})
    c.setopt(pycurl.POSTFIELDS, data)
    c.setopt(pycurl.HTTPHEADER, ["Content-Type:application/json"])
    c.perform()
    c.close()
    QtGui.QMessageBox.question(None, "Message", "Gateway was modified", QtGui.QMessageBox.Ok) #V pripade ze editovanie bolo uspesne

#Deletovanie zariadein
def delete_device(DevEui,password,name):
    c = pycurl.Curl()
    c.setopt(pycurl.USERPWD, '%s:%s' % (password,name))
    c.setopt(pycurl.HTTPHEADER, ["Content-Type:application/json"])
    c.perform()
    c.close()
    return

#Deletovanie linkov
def delete_link(Devaddr,password,name):
    c = pycurl.Curl()
    c.setopt(pycurl.CUSTOMREQUEST, "DELETE")
    url = 'http://%s:8080/links/%s' %(Server , Devaddr)
    c.setopt(c.URL, url)
    c.setopt(pycurl.USERPWD, '%s:%s' % (password,name))
    c.setopt(pycurl.HTTPHEADER, ["Content-Type:application/json"])
    c.perform()
    c.close()
    return

#De;etovanie gatewayi
def delete_gateway(Mac,password,name):
    c = pycurl.Curl()
    c.setopt(pycurl.CUSTOMREQUEST, "DELETE")
    url = 'http://%s:8080/gateways/%s' %(Server , Mac)
    c.setopt(c.URL, url)
    c.setopt(pycurl.USERPWD, '%s:%s' % (password,name))
    c.setopt(pycurl.HTTPHEADER, ["Content-Type:application/json"])
    c.perform()
    c.close()
    return

# Vystrazne okienko v pripade zadania nespravnych input parametrov
def Wrong_input_parameters_message():
    QtGui.QMessageBox.question(None, "Message", "You set wrong input parameters", QtGui.QMessageBox.Ok)

#Class ktore sluzia na zaznamenavanie dat do urcitej struktury
class device():
    def __init__(self,deveui):
        self.deveui = deveui
        self.power = ""
        self.datr = ""
        self. appkey = ""
        self.appeui = ""
        self.can_join = ""
        self.app = ""
        self.regio = ""
        self.chans = ""
        self.link = ""

class link():
    def __init__(self,devaddr):
        self.devaddr = devaddr
        self.power = ""
        self.appskey = ""
        self.nwkskey = ""
        self.app = ""
        self.regio = ""
        self.chans = ""
        self.fcnt_check = ""

class gateway():
    def __init__(self,mac):
        self.mac = mac
        self.netid = ""
        self.tx_rfch = ""

class data():
    def __init__(self,devaddr):
        self.name = devaddr
        self.data_t = []
        self.data_t.append([])
        self.data_p = []
        self.data_p.append([])
        self.data_h = []
        self.data_h.append([])
        self.data_l = []
        self.data_l.append([])
        self.hour = []
        self.hour.append([])
        self.datetime = []