import os
import socket
import select

server = socket.socket()
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(("0.0.0.0", 9000))
server.listen()

sockets = [server]

dat = {}



def nummsgs():
    return os.path.getsize("log.txt") // 80



def sendscr(client, line):
    line -= 24
    start_offset = line * 80
    num_bytes = 80 * 24
    if start_offset < 0:
        start_offset = 0
    

    with open('log.txt', "rb") as f:
        f.seek(start_offset)
        data = f.read(num_bytes)
        client.sendall(data)

    client.sendall(dat[client][1].encode('ascii'))




def mov(client, num, tofront):
    if tofront:
        dat[client][2] = -1
    elif num == -1:
        if dat[client][2] == -1:
            dat[client][2] = nummsgs() - 22
        else:
            dat[client][2] -= 22
        if dat[client][2] < 0:
            dat[client][2] = 0
    elif num == 1:
        if dat[client][2] == -1:
            pass
        else:
            dat[client][2] += 22
        if dat[client][2] > nummsgs():
            dat[client][2] = nummsgs()
    if dat[client][2] == -1:
        sendscr(client, nummsgs())
    else:
        sendscr(client, dat[client][2])

import re

allowed = r""" `1234567890-=~!@#$%^&*()_+qwertyuiop[]\QWERTYUIOP{}|asdfghjkl;'ASDFGHJKL:"zxcvbnm,./ZXCVBNM<>?"""

def sendmsg(client):
    if dat[client][0].startswith("GET"):
        return
    if dat[client][0] != 'anon':
        if dat[client][1] == '':
            mov(client, 0, True)
            return
        msg = ('<' + dat[client][0] + '> ' + dat[client][1])[:78].ljust(79) + '\n'

        with open('log.txt', 'a') as file:
            file.write(msg)

        for sock in sockets:
            if sock is not server:
                if dat[sock][2] == -1:
                    sock.sendall(('\r' + msg + dat[sock][1]).encode('ascii'))
    else:
        dat[client][0] = dat[client][1].replace("NAME> ", "")

    dat[client][1] = ''
    client.sendall(('\r' + ' '*79 + '\r').encode('ascii'))


while True:
    readable, _, _ = select.select(sockets, [], [])

    for sock in readable:
      try:
        if sock is server:
            client, addr = server.accept()
            sockets.append(client)
            dat[client] = ['anon', 'NAME> ', -1]
            print("connected:", addr)
            mov(client, 0, True)
        else:
            data = sock.recv(1)

            if not data:
                sockets.remove(sock)
                sock.close()
            else:
                try:
                 ascii = data.decode('ascii')
                 if ascii == '\n' or ascii == '\r':
                    sendmsg(sock)
                 elif data == b'\x08' or data == b'\x7f':
                    sock.sendall(b'\x08' + ' '.encode('ascii') + b'\x08')
                    dat[sock][1] = dat[sock][1][:-1]
                 elif ascii == '/' and dat[sock][1] == "":
                    mov(sock, 1, False)
                 elif ascii == '\\' and dat[sock][1] == "":
                    mov(sock, -1, False)
                 elif ascii == '\r':
                    pass
                 else:
                  if ascii in allowed:
                    sock.sendall(ascii.encode('ascii'))
                    dat[sock][1] += ascii
                except:
                    pass
      except:
        pass
