import http.server
import socketserver
import socket
import urllib.parse as up
from pathlib import Path
from html import escape

#renvoie une meilleure chaine aléatoire que le module random
from secrets import token_hex


HTTP_ACTION = {}

## PARTIE 2
# 2.1

def count(handler, path, args, isGET):
    handler.send_response(200)
    handler.end_headers()
    count = 0
    if "counter" in handler.session:
        count = handler.session["counter"]
    count += 1
    handler.session["counter"] = count
    handler.wfile.write(b"<html><body>%d</body></html>" % count)


HTTP_ACTION["count"] = count

#2.2
def genListHTML(wfile, todo):
    #todo est une liste de chaînes de caractères :
    wfile.write(b"""
    <html>
        <head>
        <meta charset='UTF-8'/>
        <title>TODO List</title>
        <style> a { background: lightgray; }
        </style>
        </head>
        <body><ul>""")
    for i in range(len(todo)):
        wfile.write(
         b"<li> %s <a href='/remove?id=%d'> (supprimer)</a>\n" %
             (escape(todo[i]).encode(), i)
        )
    wfile.write(b"""</ul>
                    <form method='get' action='/add'>
                        <input type='text' name='todo'></input><br/>
                        <button type='submit'>ajouter</button>
                        </form>""")
    wfile.write(b"""<a href='/reset'>Vider</a></ul></body></html>""")


def reset(handler, path, args, isGET):
    handler.send_response(200)
    handler.end_headers()
    handler.session["todo"] = []
    genListHTML(handler.wfile, [])

def add(handler, path, args, isGet):
    print(args)
    handler.send_response(200)
    handler.end_headers()
    if "todo" in handler.session:
        lst =  handler.session["todo"]
    else:
        lst = []
    if "todo" in args:
        lst.append(args["todo"][0])
    handler.session["todo"] = lst
    genListHTML(handler.wfile, lst)

def remove(handler, path, args, isGet):
    handler.send_response(200)
    handler.end_headers()
    if "todo" in handler.session:
        lst =  handler.session["todo"]
    else:
        lst = []
    try:
        id = int(args['id'][0])
        del lst[id]
    except:
        pass
        #plein d'erreurs possibles: id pas un entier, pas un index valide, pas présent...
    handler.session["todo"] = lst
    genListHTML(handler.wfile, lst)


HTTP_ACTION["reset"] = reset
HTTP_ACTION["add"] = add
HTTP_ACTION["remove"] = remove





## PARTIE 1

SESSION = {}
def genSessionId():
    return token_hex(16)



class CustomHTTPRequestHandler(http.server.SimpleHTTPRequestHandler):

    def __init__(self, *kwd, **args):
        self.cookies = {}
        self.session = None
        super().__init__(*kwd, **args)

    def init_cookies(self):
        for k, v in self.headers.items():
            if k == 'Cookie':
                #" c1=v1; c2=v2; ...."
                for cstring in v.split(";"):
                    fields = cstring.split("=")
                    self.cookies[fields[0].strip()] = fields[1].strip()

    def init_session(self):
        #Soit on a pas de cookie contenant notre identifiant de session
        #soit cet identifiant n'est pas dans la table de session
        if "MySessionID" not in self.cookies or \
            self.cookies["MySessionID"] not in SESSION :
            id = genSessionId()
            SESSION[id] = {}
            self.cookies["MySessionID"] = id

        self.session = SESSION[self.cookies["MySessionID"]]

    def end_headers(self):
        for c, v in self.cookies.items():
            self.send_header("Set-Cookie", c + "=" + v + "; Max-Age=600")

        super().end_headers()

    def do_GET(self):
        self.init_cookies()
        self.init_session()
        print (self.cookies)
        print (self.session)
        fields = self.path.split("?")
        path = fields[0]
        args = {}
        if len(fields) > 1:
            args = up.parse_qs(fields[1])

        if path[0] == '/':
            path = path[1:]

        p = Path('.') / path
        if p.exists():
            super().do_GET()
            return

        if path in HTTP_ACTION:
            HTTP_ACTION[path](self, path, args, True)
        else:
            self.send_error(404)
            self.end_headers()










#Petit wrapper pour qui crée un serveur TCP/IP permettant d'être interrompu
#en pressant CTRL-C dans la console
class MyHttpServer(socketserver.TCPServer):

    def server_bind(self):
        self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.socket.bind(self.server_address)

    def serve_until_interrupted(self):
        try:
            self.serve_forever()
        except KeyboardInterrupt:
            self.shutdown()
        finally:
            self.server_close()


if __name__ == "__main__":
    HTTPD = MyHttpServer(("localhost", 8080), CustomHTTPRequestHandler)
    HTTPD.serve_until_interrupted()
