package main

import (
	"flag"
	"fmt"
	"io"
	"log"
	"net"
	"os"
	"strconv"
)

var port = flag.Int("port", 8080, "port to listen on")

const welcomeMessage = `
    ____  ____  ____  ____ 
   ||D ||||O ||||D ||||O ||
   ||__||||__||||__||||__||
   |/__\||/__\||/__\||/__\|

Welcome to the Echo Server!
`

func main() {
	flag.Parse()

	// Check for environment variable first
	if envPort := os.Getenv("DODO_PORT_ECHO"); envPort != "" {
		p, err := strconv.Atoi(envPort)
		if err != nil {
			log.Fatalf("Invalid DODO_PORT_ECHO value %s: %s", envPort, err)
		}
		*port = p
	}

	// Listen on TCP port from flag
	listener, err := net.Listen("tcp", fmt.Sprintf(":%d", *port))
	if err != nil {
		log.Fatalf("Failed to start server: %s", err)
	}
	defer listener.Close()
	fmt.Printf("Echo server listening on :%d\n", *port)

	for {
		// Accept incoming connections
		conn, err := listener.Accept()
		if err != nil {
			log.Printf("Failed to accept connection: %s", err)
			continue
		}
		// Handle each connection in a separate goroutine
		go func(c net.Conn) {
			remoteAddr := c.RemoteAddr().String()
			log.Printf("New connection from %s", remoteAddr)
			if err := handleConnection(c); err != nil && err != io.EOF {
				log.Printf("Error handling connection from %s: %s", remoteAddr, err)
			}
			log.Printf("Connection closed from %s", remoteAddr)
		}(conn)
	}
}

func handleConnection(conn net.Conn) error {
	defer conn.Close()

	// Send welcome message
	if _, err := conn.Write([]byte(welcomeMessage)); err != nil {
		return fmt.Errorf("sending welcome message: %s", err)
	}

	// Create a buffer for reading data
	buffer := make([]byte, 1024)

	for {
		// Read incoming data
		n, err := conn.Read(buffer)
		if err != nil {
			return err
		}
		// Echo the data back to the client
		if _, err = conn.Write(buffer[:n]); err != nil {
			return fmt.Errorf("writing to connection: %s", err)
		}
	}
}