# -*- coding: cp1252 -*-

import time
import web
import serial
import os


from web import form

print('.................................\n')
print('............. EARTH .............\n')
print('.................................\n')

# Global variable used to debug
#### True = WebServer
#### False = Console
WEB=True

################### SERIAL CONFIGURATION ###################################
ser = serial.Serial(
    port='/dev/ttyUSB0', #COM1 for Windows or /dev/ttyUSB0 for Linux/RasPi
    baudrate= 19200,
    parity=serial.PARITY_NONE,
    stopbits=serial.STOPBITS_ONE,
    bytesize=serial.EIGHTBITS,
    timeout = 0.5
)

############################################################################

################## CONSTANT ################################################

TIME_OUT = 5 #seconds

#Number of the last instruction available on each Arduino
arduino1_max=8 #9 instructions available : 0,1,2,3...,7,8
arduino2_max=9

############################################################################

###################### WEB CONFIGURATION ###################################
if (WEB) :

    # I add a line each time I need to include a new folder
    # Weird, but it works
    urls = ('/','index',
            '/index.*','index',
            '/images/(.*)','images',
            '/css/images/(.*)','css_images',
            '/css/(.*)','css',
            '/js/(.*)','js',
            '/fonts/(.*)','fonts'
            )
    dossier_web = web.template.render('templates')
    app = web.application(urls,globals())

    #### Global variable used to save the lastest value for each sensor ###
    my_data=["Empty","Empty","Empty","Empty","Empty","Empty","Empty","Empty"]

    #Quite useless
    def my_Data():
        return my_data        

    #Class called foreach request on "/index.html" or "/"
    class index :
        def GET(self):
            data_web=my_Data()
            print("GET")
            print(data_web)
            #The function header is defined in index.html
            return dossier_web.index(data_web[0],
                                     data_web[1],
                                     data_web[2],
                                     data_web[3],
                                     data_web[4],
                                     data_web[5],
                                     data_web[6],
                                     data_web[7])

        def POST(self):
            #Someone have clicked on a button ! But, which one ?
            userdata = web.input()
            if (userdata.__contains__("btn")):
                print(userdata.btn.encode())
                state_Input_Earth(userdata.btn.encode())
            elif (userdata.__contains__("angle1")):
                angle=userdata.angle1
                print(angle)
                if(isInt(angle)):
                    message=angle+"125"
                    print(message)
                    state_Input_Earth(message.encode())
            elif(userdata.__contains__("angle2")):
                angle=userdata.angle2
                print(angle)
                if(isInt(angle)):
                    message=angle+"126"
                    print(message)
                    state_Input_Earth(message.encode())
            elif(userdata.__contains__("angle3")):
                angle=userdata.angle3
                print(angle)
                if(isInt(angle)):
                    message=angle+"127"
                    print(message)
                    state_Input_Earth(message.encode())
            elif(userdata.__contains__("angle4")):
                angle=userdata.angle4
                print(angle)
                if(isInt(angle)):
                    message=angle+"128"
                    print(message)
                    state_Input_Earth(message.encode())
            elif(userdata.__contains__("angle5")):
                angle=userdata.angle5
                print(angle)
                if(isInt(angle)):
                    message=angle+"129"
                    print(message)
                    state_Input_Earth(message.encode())
            else:
                print("Nope") #Never happened
            raise web.seeother('/')

        if __name__ == '__main__':
            app.run()

#Pour chaque folder, j'associe une classe qui va "open" au bon endroit

    #D'abord "images"...        
    class images:
        def GET(self,name):
            #J'utilise ce bout de code sans vraiment comprendre
            #si c'est nécessaire, mais au moins ca marche.
            ext = name.split(".")[-1] 

            cType = {
                "png":"images/png",
                "jpg":"images/jpeg",
                "gif":"images/gif",
                "ico":"images/x-icon"            }

            if name in os.listdir('static/images'):  # Security
                web.header("Content-Type", cType[ext]) # Set the Header
                return open('static/images/%s'%name,"rb").read() # Notice 'rb' for reading images
            else:
                raise web.notfound()

    #...puis "css"...etc !
    class css:
        def GET(self,name):
            
            if name in os.listdir('static/css'):  # Security
                return open('static/css/%s'%name,"rb").read() # Notice 'rb' for reading images
            else:
                raise web.notfound()

    class css_images:
        def GET(self,name):
            
            if name in os.listdir('static/css/images'):  # Security
                return open('static/css/images/%s'%name,"rb").read() # Notice 'rb' for reading images
            else:
                raise web.notfound()

    class js:
        def GET(self,name):
            
            if name in os.listdir('static/js'):  # Security
                return open('static/js/%s'%name,"rb").read() # Notice 'rb' for reading images
            else:
                raise web.notfound()

    class fonts:
        def GET(self,name):
            
            if name in os.listdir('static/fonts'):  # Securitys
                return open('static/fonts/%s'%name,"rb").read() # Notice 'rb' for reading images
            else:
                raise web.notfound()

############################################################################


################## TOOL BOX ################################################

def isInt(data):
        try :
                data_int=int(data)
                return True
        except ValueError :
                return False
            
def getData(canal,bool_print):
        time.sleep(0.05) #Wait the complete reception of the data          
        txt=canal.read(canal.inWaiting())
        if (bool_print):
                print("Message : '"+txt+"'")
        return txt

def inputIsValid(input):
        if (not(isInt(input))):
            return False
        
        data_int=int(input)

        ###############################################################
        #                                                             #
        # data = abc d e f (without space)                            #
        # abc : x = c+10*b+100*a ; 0 < x < 360 ; servomotor position  #
        # d : 0 = action (sensor or tool) , 1 = fetch data            #
        # e : n° of the Arduino                                       #
        # f : n° of the sensor                                        #
        #                                                             #
        ###############################################################

        capteur_n0=data_int % 10
        data_int = data_int /10
        
        arduino_n0=data_int % 10
        data_int = data_int /10

        is_action=data_int%10
        if is_action!=0:
            print("----> Type : order")
        else :
            print("----> Type : request")

        angle = data_int / 10

        if (angle < 0 or angle > 360):
            return False

        if (is_action < 0 or is_action > 1):
            return False

        if angle!=0 :
             print("----> Angle : "+str(angle))
        return isValid(arduino_n0,capteur_n0)
         

def isValid(arduino_n0,capteur_n0):
        isCorrect = False
        if (arduino_n0==1):
                print("----> Arduino n 1 selected")
                isCorrect = (capteur_n0 >=0  and capteur_n0 <= arduino1_max)
        elif (arduino_n0==2):
                print("----> Arduino n 2 selected")
                isCorrect = (capteur_n0 >=0  and capteur_n0 <= arduino2_max)
        else:
                print("----> Arduino number unknown : "+str(arduino_n0))
        if(not isCorrect):
                print("----> Capteur unknown "+str(capteur_n0))
        else:
                print("----> Capteur n "+str(capteur_n0))
        return isCorrect

##############################################################################

def state_Input_Earth(input):
        # If user wants to exit
        if input == 'exit':
                #Exit
                ser.close()
                print("----> Exit ")
                exitflag = 1
                while exitflag > 0:
                        pass
                        exit()
        else :
                if (not(inputIsValid(input))):
                    #### SHOULD BE SEND TO THE SERVER ###
                    print("----> ERROR ! Input is not valid")
                else :
                    go=True
                    if ser.inWaiting()!=0 :
                            # Not handled for the moment
                            if(getData(ser,False)=="HELP"):
                                    print(" !!!!!!!!!!!!! ROVER HAVE A PROBLEM !!!!!!!!!!!!!!")
                                    go = False
                            else :        
                                    print("----> Flush ")
                                    #Flush buffer (avoid old message) ! 
                                    flush =ser.read(ser.inWaiting())
                    if (go):
                            is_action = (int(input)/100)%10
                            if (is_action):
                                print("----> Send an order ")
                                state_Send(input)
                            else :
                                print("----> Send a request ")
                                state_Send_and_Wait(input)

def state_Send(input):
        # Send instruction
        ser.write(input)

        ########### CHECK ??? ########"
        print("----> END")
        print("");


def state_Send_and_Wait(input):
        # Send instruction
        ser.write(input)

        # We wait the "check" 5 sec
        waiting=1
        time_end=time.time() + TIME_OUT*2
        while waiting==1:
            if ser.inWaiting()!=0 or time.time()>time_end:
                waiting=0
                if ser.inWaiting()!=0:
                        state_Order_Arrived(int(input)%10)
                else :
                        print("----> Transmission : TIMEOUT")
        #MAY BE DELETED
        print("----> END")
        print("");


def state_Order_Arrived(input) :
        ### We have a message : the Rover have answered
        print("----> Transmission : Message received by the Rover")
        data=getData(ser,True)

        ### Check if the Rover understood ?

        print("COUCOU")
        if (WEB):
            global my_data
            my_data[input-1]=data
            raise web.seeother('/')

        
############################################################################


#############################  MAIN  #################################
if (not(WEB)):
    while 1 :
        # Wait for user instructiom
        input = raw_input(">>")
        state_Input_Earth(input)

    

        
    
