#!/usr/bin/env python3
# raw sockets on Linux

import socket, sys, time, random
from struct import *
import netifaces as ni
from connection import Connection 
import ip_handle as ip
import tcp_handle as tcp
import http_handle as http
import random

# This function handles the creation of connection, namely creating the raw sockets
# for sending and the (less raw) socket for receving, handle all the necessary ip
# addresses and port for sending stuff, and create an instance of the 
# connection class that takes the two sockets.
# INPUT: dest_ip
# RETURN: Connection conn (an instance of the connection class defined in connection.py)
def create_connection(dest_ip):
    
    # create a new send socket with SOCK_RAW/IPPROTO_RAW
    try:
        s_send = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
    except (socket.error, msg):
        print('Socket could not be created. Error code:' + str(msg[0]) + msg[1])
        sys.exit()

    # create a new recv socket with SOCK_RAW/IPPROTO_IP
    try:
        s_recv = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_TCP)
    except (socket.error, msg):
        print('RecvSock creation error. Code: ' + str(msg[0]) + msg[1])
        sys.exit()

    source_ip = ni.ifaddresses('ens33')[ni.AF_INET][0]['addr']
    # and find a valid port to send (just uses socket.bind and let system figure this out)
    s_send.bind((source_ip, 0))
    source_port = s_send.getsockname()[1]

    # getting a random big port, for testing
    #source_port = random.randrange(5000, 60000)

    conn = Connection(source_ip, dest_ip, source_port, s_send, s_recv)

    return conn


# the function for handling the main logic of this homework.
# namely it handles the url from command line, figures out what the download
# name and ip addresses should be, create connection, establish handshake,
# send http get, then start receiving data, and then finally open a file and
# writes the received data in.
def main():
    # get download url from args and get ip and split out/create file name
    dest_url = sys.argv[1]
    host_name = dest_url.split("//")[1].split("/")[0]
    if (len(dest_url.split("//")[1].split("/")) > 1):
        if dest_url.endswith('/'):
            file_path = dest_url.split("//")[1].split("/", 1)[1]
            file_name = 'index.html'
        else:
            file_path = dest_url.split("//")[1].split("/", 1)[1]
            file_name = dest_url.split("//")[1].split("/")[-1]
    else:
        file_name = 'index.html'
        file_path = '/'
    #print(file_name + " is file name\n")
    
    dest_ip = socket.gethostbyname(host_name)
    conn = create_connection(dest_ip)

    # send the syn packet to start the connection
    tcp_flags = {'syn':1, 'ack':0, 'fin':0}
    conn.send(tcp_flags, b'')

    conn.recv_pkt(4069)

    # now send the http request
    tcp_flags = {'syn':0, 'ack':1, 'fin':0}
    data = http.http_get(file_path, host_name)
    data = data.encode()
    #if len(data) % 2 == 1:
    #    data = data + b'0'
    conn.send(tcp_flags, data)

    # and receive the actual file i guess
    response = http.get_message(conn)
    f = open(file_name, 'wb')
    f.write(response[0])
    f.close()
    
    #while len(conn.recv(6000)) > 0:
    #    pass
        
    # and then close the connection on our side
    tcp_flags = {'syn':0, 'ack':1, 'fin':1}
    conn.send(tcp_flags, b'')

        
 


if __name__ == "__main__":
    main()
    
    
    
