#!/usr/bin/env python3
# -*- coding: utf-8 -*-
###############################################################################
#
# Copyright Lars Hagström, 2015 (lars@foldspace.nu)
# Copyright Niels Simonsen, 2015 (nesnomis@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 sys, subprocess, re, traceback, time
from PyQt5 import QtWidgets
from PyQt5 import QtGui
from PyQt5 import QtCore
from threading import Thread
from queue import Queue, Empty
import json
import socket
import socketserver

def send_json(message):
    TCP_IP = '127.0.0.1'
    TCP_PORT = 8004
    
    if "id" not in message:
        message["id"] = "null"

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    connected = False
    for i in range(3):
        try:
            s.connect((TCP_IP, TCP_PORT))
            connected = True
        except:
            time.sleep(0.5)
    if not connected:
        raise Exception("failed to connect")
    s.send(json.dumps(message).encode("UTF-8"))
    
    result = json.loads(s.recv(1024*8).decode("UTF-8"))
    s.close()
    #print (result)
    if "result" in result and result["result"] != "ok":
        raise Exception ("Command", message, "resulted in an error:", result)
    if "error" in result:
        raise Exception ("Command", message, "resulted in an error:", result)
"""
def enqueue_output(out, queue):
    pattern = re.compile(r"^ *[0-9]+\. (.*) \(([0-9\.]+)\)")
    while True:
        line = out.readline()
        if not line:
            break
        match = pattern.match(line)
        if match is not None:
            queue.put((match.group(1),match.group(2)))
    out.close()
"""

def sendmessage(title, message):
    subprocess.call(("notify-send", title, message, "--icon=info"))

class SystemTrayIcon(QtWidgets.QSystemTrayIcon):

    def __init__(self, icon, parent=None):
        QtWidgets.QSystemTrayIcon.__init__(self, icon, parent)
        self.activated.connect(self.update)
        self.menu = QtWidgets.QMenu(parent)
        self.toggleServiceAction = self.menu.addAction("Restart Streaming Service")
        self.toggleServiceAction.triggered.connect(self.toggleService)

        self.menu.addSeparator()
        #self.deviceMenu = self.menu.addMenu("Stream to")

        self.connectIp = self.menu.addAction("Connect to IP")
        self.connectIp.triggered.connect(self.inputIpDialog)
        
        self.menu.addSeparator()
        self.menu.addAction("Exit").triggered.connect(self.exit)
        self.setContextMenu(self.menu)

        #self.scanProc = None
        #self.devices = set()

    def update(self):
        running = False
        output = subprocess.check_output(("systemctl","--user","show","airtame-streamer.service"))
        if output.find(b"ActiveState=active") != -1:
            self.toggleServiceAction.setText("Stop Streaming Service")
            running = True
        elif output.find(b"ActiveState=inactive") != -1:
            self.toggleServiceAction.setText("Start Streaming Service")
        else:
            self.toggleServiceAction.setText("Restart Streaming Service")

        #self.deviceMenu.setEnabled(running and len(self.devices) > 0)

        #if running:
        #    self.deviceMenu.clear()
        #    for (name,addr) in self.devices:
        #        action = self.deviceMenu.addAction("Stream to " + name)
        #        action.triggered.connect(lambda: self.stream(name))
    """
    def startScan(self):
        if self.scanProc is None:
            self.scanProc = subprocess.Popen(("stdbuf", "-oL", "airtame-tray-cli", "-s"),
                                             stdout=subprocess.PIPE,
                                             stderr=subprocess.STDOUT,
                                             universal_newlines = True)
            self.scanQueue = Queue()
            thread = Thread(target=enqueue_output,args=(self.scanProc.stdout, self.scanQueue))
            thread.daemon = True
            thread.start()
            self.scanTimer = QtCore.QTimer()
            self.scanTimer.timeout.connect(self.collectScanResults)
            self.scanTimer.start(2000)

    def stopScan(self):
        if self.scanProc is not None:
            self.scanProc.kill()
            self.scanProc = None
            self.scanTimer.stop()
            self.scanTimer = None

    def collectScanResults(self):
        while not self.scanQueue.empty():
            res = self.scanQueue.get_nowait()
            if res not in self.devices:
                self.devices.add(res)
                self.update()
                sendmessage("Airtame detected", "Name: " + res[0] + "\nAddress: " + res[1])
    """
    def exit(self):
        print("Exiting")
        subprocess.call(("systemctl","--user","stop","airtame-streamer.service"))
        #self.stopScan()
        QtWidgets.QApplication.quit()

    def toggleService(self):
        print (self.toggleServiceAction.text())
        init = False
        if self.toggleServiceAction.text() == "Start Streaming Service":
            subprocess.call(("systemctl","--user","start","airtame-streamer.service"))
            init = True
        elif self.toggleServiceAction.text() == "Stop Streaming Service":
            subprocess.call(("systemctl","--user","stop","airtame-streamer.service"))
        elif self.toggleServiceAction.text() == "Restart Streaming Service":
            subprocess.call(("systemctl","--user","restart","airtame-streamer.service"))
            init = True

        if init:
            send_json({"method": "initStreamer"})
            send_json({"method": "registerListener",
                       "params" : ["127.0.0.1", "8005"]})

    def inputIpDialog(self):
        text, ok = QtWidgets.QInputDialog.getText(None,
                                                  'Airtame IP',
                                                  'Enter Airtame IP address:')
        if ok:
            self.stream(text)

    def stream(self, name):
        xrandr_output = subprocess.check_output(("xrandr")).decode("utf-8")
        if xrandr_output.count("\*"):
            sendmessage("NO!", "More than one screen connected, will not start streaming")
            return
        send_json({"method": "connect",
                   "params" : [name, "8002"]})

"""
class InfoListener(socketserver.ThreadingTCPServer):
    allow_reuse_address = True

class InfoListenerHandler(socketserver.StreamRequestHandler):
    def handle(self):
        try:
            self.request.setblocking(True)
            data = ""
            while True:
                data += self.rfile.readline().decode("ascii")
                print(data)
                break
                #TODO: make a proper message pump here.
                #data = json.loads(self.request.recv(8*1024).decode("UTF-8"))
                # process the data, i.e. print it:
                #print( data)
                # send some 'ok' back
                #self.request.sendall(json.dumps({"id" : data["id"], 'result':'ok'}).encode("utf-8"))
        except Exception as e:
            print ("Exception wile receiving message: ", e)
"""
def listener():
    TCP_IP = '127.0.0.1'
    TCP_PORT = 8005

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.bind((TCP_IP,TCP_PORT))
    s.listen(1)
    conn, addr = s.accept()
    data = ""
    while True:
        more = conn.recv(10).decode("ascii")
        if more == "":
            print("Listener connection is dead")
            break
        data += more
        lines = data.splot("\n")
        if lines[0] == "{":
            msg = ""
            for line in data.split("\n"):
                msg += line
                if line == "}":
                    break
        
        print (data)
        time.sleep(0.1)
    conn.close()


def main():
    app = QtWidgets.QApplication(sys.argv)
    app.setQuitOnLastWindowClosed(False)

    w = QtWidgets.QWidget()
    trayIcon = SystemTrayIcon(QtGui.QIcon("/opt/airtame/logo.png"), w)

    """
    server = InfoListener(('127.0.0.1', 8005), InfoListenerHandler)
    thread = Thread(target=server.serve_forever)
    thread.daemon = True
    thread.start()
    """
    thread = Thread(target=listener)
    thread.daemon = True
    thread.start()
    
    trayIcon.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()
