#!/usr/bin/env python3
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 8 -*- 
# main.py
# Copyright (C) 2019 John Coppens <john@jcoppens.com>
# test_multi 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.
# test_multi is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# 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 gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GLib, Gio
import os, sys
import pdb
import socket
import fcntl
import subprocess as sp

UI_FILE = "test_multi.ui"
RTC_DEV = "/dev/rtc0"
IP      = ""
PORT    = 9999
XTERM   = "xterm"

RTC_UIE_ON = 0x00007003

class RTC():
    """ RTC connects a handler to the RTC device (normally /dev/rtc0)
            <callback> parameter    if defined, will be called on each tick
            <viewer> parameter      if defined, must be a Gtk.TextView, and a
                                    character will be inserted on each tick

        NOTE: At the moment, the 'tick' signal is the default 1 second period.
            The rate can be changed with ioctl commands, but this is NOT
            implemented here for simplicity.
    def __init__(self, parent, viewer = None, callback = None):
        self.parent = parent
        self.callback = callback
        self.viewer = viewer
        self.rtc = open(RTC_DEV, "rb")
        if not self.rtc:
            print("Can't open file:", RTC_DEV)
        self.ioch = GLib.IOChannel.unix_new(self.rtc.fileno())
        # Datos leidos del RTC son del tipo 'long': No son caracteres validos
        # y es preciso de deshabilitar la codificacion:
        GLib.io_add_watch(self.ioch, GLib.IO_IN, self.read)

    def read(self, ioch, par2):
            data = self.ioch.read(8)    # Cada 'long' tiene 8 bytes
        except Exception as e:
            print("Data read contains strange things")
        return True

    def enable_interrupts(self):
        r = fcntl.ioctl(self.rtc, RTC_UIE_ON, 0)
        if r == -1:
            print("Could not enable interrupts")

    def append_text(self, txt):
        if self.callback != None:
        bff = self.viewer.get_buffer()
        bff.insert(bff.get_end_iter(), txt)

    def disable_interrupts(self):
        fcntl.ioctl(self.rtc, RTC_UIE_OFF, 0);

class TCP_client():
    """ The TCP client tries to connect to the server on instantiation of the
        class. So the server must be running!
            <callback> parameter    if defined, will be called with the data
                                    received on the TCP port.
            <viewer> parameter      if defined, must be a Gtk.TextView, and
                                    will be updated with the received data.
            semd method             can be called to send a message to the
                                    TCP port
    def __init__(self, host, port,
                callback = None,
                viewer = None):
        self.callback = callback
        self.viewer = viewer

        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        self.socket.connect((host, port))
        self.fd = self.socket.fileno()             # Obtener el file descriptor
        print("Connected to {}".format(host))
        GLib.io_add_watch(self.fd, GLib.IO_IN, self.process_input)
                                                   # Instalar la funcion en caso
                                                   # de datos recibidos

    def process_input(self, skt, cond):
        """ This function is called asynchronously when data is received.
        msg = self.socket.recv(100)                # Recibir el mensage de la red
        if self.callback != None:
        bff = self.viewer.get_buffer()
        bff.insert(bff.get_end_iter(), msg.decode("latin-1"))
        return True                                # Queremos quedar activos

    def send(self, msg):

class GUI:
    def __init__(self):
        self.builder = Gtk.Builder()

        main_window = self.builder.get_object("MainWindow")
        # Make an dictionary of references to widgets we are interested in
        # from the UI file
        self.obj = {}
        for objref in ["from_RTC_buffer",
            self.obj[objref] = self.builder.get_object(objref)

        self.rtc = RTC(self,
                    viewer = self.obj["from_RTC_view"],
                    callback = self.process_rtc)

        self.tcp = TCP_client(IP, PORT, 
                    viewer = self.obj["from_socket_view"],
                    callback = self.process_tcp)
        self.tcp.send("Simulated server (netcat) \n")


    def on_window_destroy(self, window):

    def process_rtc(self, data):
        """ Execute anything which has to be synced with the RTC
        return True

    def process_tcp(self, data):
        """ Process the data coming from the server
        return True

    def kbd_entry_activate_cb(self, entry):
        """ Send the data from the keyboard to the server (and print
            on the terminal
        text = entry.get_text()
        self.tcp.send(text + "\n")

def main():
    sp.Popen([XTERM, '-e', 'nc', '-l', '-p', '9999'])
    gui = GUI()
if __name__ == "__main__":