# -*- coding: UTF-8 -*-
import urllib
import RaspberryPi
from Db import Db_MySQL
import json
import time , os
import subprocess
import socket
import re
from datetime import datetime
import gzip


class gestionnaireConnection :
    version_pyUpload = '2.16'
        
    def __init__(self):
        self.fbname = RaspberryPi.getFBName()
        self.serial = RaspberryPi.getSerial()
        self.mac = RaspberryPi.getHWAdrr()
        self.db = Db_MySQL()
        self.db.initCnx() 
        self.parametreParDefaut = {'Serial': self.serial, 'HWaddr': self.mac, 'FBname': self.fbname, 'IdConfig' : self.db.getIdConfig() }


    def formateData(self, listePdmDateFrom , limitNbResult):
        d = self.db.getData2send(listePdmDateFrom, limitNbResult=limitNbResult)
        return json.dumps(d , separators=(',', ':'))
            
    def getRequeteRequeteServer(self, paramEnPlus={ 'Demande' : 'getPackage' }):
        
        params = self.parametreParDefaut.copy() 
        for p in paramEnPlus :
            params[p] = paramEnPlus[p]
            
        with open('/proc/uptime', 'r') as f:
            params['uptime_secondes'] = float(f.readline().split()[0])
                                
#         params['padding'] = 'A'.join('{0:4X}'.format(c) for c in range(0x1111, 0x1111 + 3000))        
        
        data = urllib.urlencode(params)    
        
        data2write = '\r\n'.join([
           'POST /upload/maintenance.php HTTP/1.0' ,
           'HOST: tempsreel.histoconso.com' ,
           'Content-type: application/x-www-form-urlencoded',
           'User-Agent: %s v%s.py' % (self.fbname, self.version_pyUpload),
           'Content-Length: {0:d}'.format(len(data)) ,  # Nécessaire sinon ça ne fonctionne pas 
           '',
           data,
           ''
         ])
        
        return data2write
    
    def send2WebServer(self, paramEnPlus={ 'Demande' : 'getPackage' }):    
        
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect(("tempsreel.histoconso.com" , 80))
                
        data2send = self.getRequeteRequeteServer(paramEnPlus)        
                
        s.sendall(data2send)
        
        time.sleep(2)
    
        data = ""
                
        # On reçoit et affiche la réponse du serveur
        while 1:
            d = s.recv(1024)
            if not d: 
                break
            data = data + d
            
        s.close()
        
        contentType = ""
        body = ""
        
        data = data.strip()
        
        index_frontiere_header_body = data.find('\r\n\r\n')
                
        if index_frontiere_header_body > 0 :
            header = data[0:index_frontiere_header_body] + '\r\n'
            body = data[index_frontiere_header_body + 4:len(data)]
            
#           print( "Je vois header : {} et body : {}<=".format( header.strip() , body ) )
                            
            result = re.search(r'[Cc]ontent-[Tt]ype: ([\w\W]+)\r\n', header)
            if result != None :
                contentType = result.group(1)
#                         print(contentType)

               
        return (contentType , body)
    
    def gereReponse(self , contentType, contenu , limiteNbReponse=1440 * 15):
                
        if contentType == None :
            return None         
                
        result = None
        
        if len(contentType) == 0 :
            print("Je n'ai pas réussi à lire le content-type de la réponse")        
                
        elif 'application/force-download' in contentType :
            # C'est un fichier zip à traiter
            return self.executePackageRecu(contenu)            
        else : 
            try :
                d = json.loads(contenu)
                
                if 'ts' in d :
                    
                    str_dateTimeServeur = datetime.fromtimestamp(int(d["ts"])).strftime('%Y-%m-%d %H:%M:%S')
                    
                    if abs(d["ts"] - time.time()) > 60 * 5 :
                        # Si l'heure du serveur diffère de plus de 5 minutes, je change
                        print("Je change ma date de {} à {}".format(datetime.fromtimestamp(int(time.time())).strftime('%Y-%m-%d %H:%M:%S') , str_dateTimeServeur))
                        os.system('date -s "{}"'.format(str_dateTimeServeur))
#                     else :
#                         print("J'aurai pu changer la date avec {}".format('date -s "{}"'.format(datetime.datetime.fromtimestamp(int(d["ts"])).strftime('%Y-%m-%d %H:%M:%S'))))

                if "config" in d :
                    # Il faut changer la config
                    self.db.appliquerConfig(d["config"])
                                    
                if "T24h" in d :
                    self.db.insereTemperature(d["T24h"])    
                
                if "lastData" in d :
                    # Il faut remonter des données
                    
                    print("On demande les données depuis {}".format(d["lastData"]))
                    
                    newData = self.formateData(d["lastData"] , limitNbResult=limiteNbReponse)
                    
                    if len(newData) > 2 :  # C'est une string len('[]') == 2 ...
                        result = {'Demande':'sendData' , 'dataJSON' : newData }
                    else :
                        print("Pas de nouvelles données à remonter")
                    
            except ValueError as e :
                print("Problème pour décoder du json dans {1} de type {0}".format(contentType , contenu))
            except Exception as e :
                print("Problème avec {} , {}".format(contenu , e))
                
        return result
    
    def getPackage(self):
        
        for _ in range(0 , 30):
        
            contentType, contenu = self.send2WebServer()
            
            newData = self.gereReponse(contentType, contenu)
             
            if newData != None :
                self.send2WebServer(newData)
            else :
                break
          
        return None
    
    def executePackageRecu(self, contenu):
        
        reponse = None        
                
        tmpName = 'pyF.%s' % (long(round(time.time())))        
        tmpFile = '/tmp/%s.pak' % (tmpName)
        tmpDir = '/tmp/%s' % (tmpName)
        
        # On écrit le contenu dans un fichier pour pouvoir le dezipper...           
        with open (tmpFile, 'a') as f:
            f.write (contenu)
        p = subprocess.Popen([ "unzip" , tmpFile , "-d" , tmpDir ] , stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        out, err = p.communicate()
        
        fileRunSh = '%s/run.sh' % tmpDir
                
        if os.path.exists(fileRunSh):
            p = subprocess.Popen([ "/bin/sh" , fileRunSh ] , stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            out, err = p.communicate()
            
            reponse = {'Demande': 'sendReponse', 'Reponse': out , 'Erreurs': err }
        
        # On nettois les fichiers temporaires
        subprocess.call(['/bin/rm -rf %s*' % (tmpDir) ] , shell=True)
        return reponse         
        
if __name__ == '__main__':
    gestionnaireConnection().getPackage()   
