import socket
import threading
import os
import config as cfg
from connection.socket import SocketServer
from connection.socket import SocketHTTP
from tcp import models
import time
from tcp import utils
import tcp as t
from types import SimpleNamespace

class Connector():

    def __init__(self, parser,socket):
        self.parser = parser
        self.server = None
        self.serverDomain = None
        self.serverIP = None
        self.s = SocketServer(socket,self.parser,"Connector")
        self.buffer = []
        self.handshaked = False
        self.t = threading.Thread(target=self.tcp)
        
        print("\n\n Connector\n\n")
        

    def recv(self,data):
        try:
            self.buffer.append(data)
            if not self.t.is_alive():
                self.t.start()
        except:
            print("\33[41m\33[41mAn exception occurred recv\33[0m" )

    def oracleInitial(self,data):
        try:
            while len(self.s.connected) < 2:
                time.sleep(.5)
            if(len(self.s.connected) == 2):
                # if self.s.connected[0].addr[0] == data["bearer"]  and  self.s.connected[1].addr[0] == data["cryptor"]:
                    self.bearer = self.s.connected[1]
                    self.cryptor = self.s.connected[0]
                # elif self.s.connected[1].addr[0] == data["bearer"]  and  self.s.connected[0].addr[0] == data["cryptor"]:
                #     self.bearer = self.s.connected[1]
                #     self.cryptor = self.s.connected[0]
                # else:
                #     raise Exception("Error") 
                    

            self.serverDomain = data["server"]
            if type(self.serverDomain) == str:
                self.serverDomain = [self.serverDomain]
            # self.serverIP = socket.gethostbyname(data["server"])
            self.serverIP = "216.58.205.228"
            self.server = SocketHTTP(self.serverIP,443,self)
        except Exception as e:
            print("\33[41m\33[41mAn exception occurred oracleInitial Connector ",e,"\33[0m" )
        
    def keyExchange(self,data):
        try:
            while not self.server: 
                time.sleep(.5)
            self.key_exchange =bytes.fromhex( data["keyExchange"])
            self.server.send(bytes.fromhex(self.client_hello()))
        except NameError:
            print(NameError)
            print("\33[41mAn exception occurred keyExchange Connector,\33[0m")

    # def toCryptor(self,data):
    #     try:
    #         self.key_exchange =bytes.fromhex( data["keyExchange"])
    #         self.server.send(bytes.fromhex(self.client_hello()))
    #     except NameError:
    #         print(NameError)
    #         print("\33[41mAn exception occurred keyExchange Connector,\33[0m")


    def client_hello(self):
        try:
            print("Done 1")
            extensions = [
                models.ClientExtension.server_names(self.serverDomain),
                models.ClientExtension.supported_versions([b"\x03\x04"]),
                models.ClientExtension.key_share(
                    [models.KeyShareEntry(models.NamedGroup.x25519, self.key_exchange)]
                ),
                models.ClientExtension.signature_algorithms(list(models.SignatureScheme)),
                models.ClientExtension.supported_groups([models.NamedGroup.x25519]),
            ]


            
            compatibility_mode = True
            handshake = models.Handshake(
                models.HandshakeType.client_hello,
                models.ClientHello(
                    ...,
                    os.urandom(32),
                    os.urandom(32) if compatibility_mode else b"",
                    list(models.CipherSuite),
                    ...,
                    extensions,
                ),
            )
            self.client_hello_data = handshake.binary
            self.handshake_context = bytearray(self.client_hello_data)
            self.parser.parserSend(bytes(self.client_hello_data).hex(),self.cryptor,"fromContoCryHelloCLient")

            data = models.ContentType.handshake.tls_plaintext(self.client_hello_data)
            return bytes.hex(data)
        except Exception as exception:
            print("\33[41mAn exception occurred client_hello Connector,\33[0m",exception)


    def tcp(self):
        while 1: 

            time.sleep(0.5)
            while self.buffer and self.buffer[0] and len(self.buffer[0])>=10:
                s = self.buffer[0][6:10]
                print(s)
                l = int(s,16)*2+10
                a = self.lenCalc(l)
                if not self.handshaked:
                    self.parser.parserSend(a,self.cryptor,"fromContoCry")
        self.t.exit()



    def lenCalc(self, len2):
        if len(self.buffer[0]) > len2:
            a = self.buffer[0][:len2]
            self.buffer[0] = self.buffer[0][len2:]
            return a
        elif len(self.buffer[0]) == len2 :
            return self.buffer.pop(0)
        elif len(self.buffer[0]) < len2 :
            if self.buffer[1]:
                self.buffer[0] = self.buffer[0] + self.buffer[1]
                self.buffer.pop(1)
                return lenCalc(self.buffer,len2)
            else:
                print("Data is not copmlete1 ")
                time.sleep(1)
                lenCalc(self.buffer,len2)
        else: 
            print("Data is not copmlet2e")
            time.sleep(1)
            lenCalc(self.buffer,len2)

    

    def MPC(self,data):
        try:
            print("TODO") # TODO
        except Exception as exception :
            print("\33[41mAn exception occurred MPC Connector " ,exception,"\33[0m" )   

    def fromCrytoCon(self,data):
        try:
            print("TODO fromCrytoCon") # TODO
        except Exception as exception :
            print("\33[41mAn exception occurred fromCrytoCon Connector " ,exception,"\33[0m" )   

