package main

import (
	"crypto/tls"
	"fmt"
	"io"
	"log"
	"net/url"
	"strings"
)

type Responce struct {
	Status string
	Meta   string
	Body   string
}

type Request struct {
	URL string
}

type Client struct {
	InsecureSkipVerify bool
}

var config = tls.Config{
	InsecureSkipVerify: true,
}

var DefaultClient = &Client{}

func Fetch(args ...string) {
	DefaultPort := "1965"
	if len(args) < 2 {
		DefaultClient.Fetch(args[0], DefaultPort)
	}
	if len(args) > 2 {
		log.Fatal("too many args passed, just want URL and PORT")
	}
	if len(args) == 2 {
		DefaultClient.Fetch(args[0], args[1])
	}
}

func (c Client) Fetch(URL string, port string) {
	conn := c.connect(URL, port)
	defer conn.Close()

	resp, err := c.getResponse(conn, URL)
	if err != nil {
		log.Fatal(err)
	}
	//fmt.Printf("resp: %s, %s\n", resp.Status, resp.Meta)
	fmt.Printf("----------\n%s", resp.Body)
}

func (c Client) connect(URL string, port string) *tls.Conn {
	parsedURL, err := url.Parse(URL)
	if err != nil {
		log.Fatal(err)
	}

	conn, err := tls.Dial("tcp", parsedURL.Host+":"+port, &config)
	if err != nil {
		log.Fatalf("failed to connect: %v", err)
	}
	return conn
}

// func (c Client) getResponse(connection *tls.Conn, URL string) {
func (c Client) getResponse(connection *tls.Conn, URL string) (Responce, error) {
	err := c.sendRequest(connection, URL)
	if err != nil {
		log.Fatal(err)
		return Responce{}, err
	}
	body := handleBody(connection)
	first, second := getFirstTwoWords(body)
	return Responce{
		Status: first,
		Meta:   second,
		Body:   body[(len(first) + len(second)):],
	}, nil

}

func getFirstTwoWords(input string) (string, string) {
	reply := strings.Split(strings.Split(input, "\n")[0], " ")
	return reply[0], reply[1]
}

func handleBody(connection *tls.Conn) string {
	buf := make([]byte, 4096)
	var body []byte

	for {
		n, err := connection.Read(buf)
		if err != nil {
			//handle EOF
			if err == io.EOF {
				break
			}
			log.Fatal(err)
		}

		body = append(body, buf[:n]...)
	}
	return string(body)

}

func (c Client) sendRequest(connection *tls.Conn, requestURL string) error {
	CRLF := "\r\n"
	_, err := connection.Write([]byte(requestURL + CRLF))
	if err != nil {
		log.Fatal(err)
		return err
	}
	//fmt.Printf("request (%d bytes) sent...\n", reqSize)
	return nil
}
