Imports System.Net
Imports System.Net.Sockets
Imports System.Text
Imports System.IO
Imports System.Threading

Public Class Form1
    Private serverSocket As TcpListener
    Private isServerRunning As Boolean = False
    Private serverThread As Thread
    Private connectionCount As Integer = 0

    Private Sub FormMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        ' Initialize form
        LoadIPAddress()
        Txt_ServerPath.Text = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
        AddLog("Server initialized. Ready to start.")
    End Sub

    Private Sub LoadIPAddress()
        ' Get local IP address
        Try
            Dim hostName As String = Dns.GetHostName()
            Dim ipAddresses As IPAddress() = Dns.GetHostAddresses(hostName)

            For Each ip As IPAddress In ipAddresses
                ' Get IPv4 address
                If ip.AddressFamily = AddressFamily.InterNetwork Then
                    Txt_IPAddress.Text = ip.ToString()
                    Exit For
                End If
            Next

            If String.IsNullOrEmpty(Txt_IPAddress.Text) Then
                Txt_IPAddress.Text = "127.0.0.1"
            End If
        Catch ex As Exception
            Txt_IPAddress.Text = "127.0.0.1"
            AddLog("Error getting IP address: " & ex.Message)
        End Try
    End Sub

    Private Sub btnStartServer_Click(sender As Object, e As EventArgs) Handles Btn_StartServer.Click
        StartServer()
    End Sub

    Private Sub btnStopServer_Click(sender As Object, e As EventArgs) Handles Btn_StopServer.Click
        StopServer()
    End Sub

    Private Sub btnBrowse_Click(sender As Object, e As EventArgs) Handles Btn_Browse.Click
        If FolderBrowserDialog1.ShowDialog() = DialogResult.OK Then
            Txt_ServerPath.Text = FolderBrowserDialog1.SelectedPath
            AddLog("Folder selected: " & Txt_ServerPath.Text)
        End If
    End Sub


    Private Sub btnClearLog_Click(sender As Object, e As EventArgs) Handles Btn_ClearLog.Click
        Txt_Log.Clear()
        AddLog("Log cleared.")
    End Sub

    Private Sub StartServer()
        Try
            ' Validate port
            Dim port As Integer
            If Not Integer.TryParse(Txt_Port.Text, port) OrElse port < 1 OrElse port > 65535 Then
                MessageBox.Show("Please enter a valid port number (1-65535)", "Invalid Port", MessageBoxButtons.OK, MessageBoxIcon.Error)
                Return
            End If

            ' Validate path
            If Not Directory.Exists(Txt_ServerPath.Text) Then
                MessageBox.Show("The specified directory does not exist!", "Invalid Path", MessageBoxButtons.OK, MessageBoxIcon.Error)
                Return
            End If

            ' Start server
            serverSocket = New TcpListener(IPAddress.Any, port)
            serverSocket.Start()
            isServerRunning = True

            ' Start listening thread
            serverThread = New Thread(AddressOf ListenForClients)
            serverThread.IsBackground = True
            serverThread.Start()

            ' Update UI
            UpdateUI(True)
            AddLog("========================================")
            AddLog("✓ Server STARTED successfully!")
            AddLog("✓ Listening on: " & Txt_IPAddress.Text & ":" & port)
            AddLog("✓ Serving files from: " & Txt_ServerPath.Text)
            AddLog("✓ Waiting for connections...")
            AddLog("========================================")

        Catch ex As Exception
            MessageBox.Show("Error starting server: " & ex.Message, "Server Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
            AddLog("✗ Error starting server: " & ex.Message)
            StopServer()
        End Try
    End Sub

    Private Sub StopServer()
        Try
            isServerRunning = False

            If serverSocket IsNot Nothing Then
                serverSocket.Stop()
                serverSocket = Nothing
            End If

            If serverThread IsNot Nothing AndAlso serverThread.IsAlive Then
                serverThread.Abort()
                serverThread = Nothing
            End If

            UpdateUI(False)
            AddLog("========================================")
            AddLog("✓ Server STOPPED")
            AddLog("========================================")

        Catch ex As Exception
            AddLog("✗ Error stopping server: " & ex.Message)
        End Try
    End Sub

    Private Sub ListenForClients()
        While isServerRunning
            Try
                If serverSocket.Pending() Then
                    Dim client As TcpClient = serverSocket.AcceptTcpClient()
                    Dim clientThread As New Thread(Sub() HandleClient(client))
                    clientThread.IsBackground = True
                    clientThread.Start()
                Else
                    Thread.Sleep(100)
                End If
            Catch ex As ThreadAbortException
                Exit While
            Catch ex As Exception
                If isServerRunning Then
                    AddLog("✗ Error accepting client: " & ex.Message)
                End If
            End Try
        End While
    End Sub

    Private Sub HandleClient(client As TcpClient)
        Dim clientEndPoint As IPEndPoint = CType(client.Client.RemoteEndPoint, IPEndPoint)
        Dim clientIP As String = clientEndPoint.Address.ToString()
        Dim clientPort As Integer = clientEndPoint.Port

        IncrementConnectionCount()
        AddLog("")
        AddLog("[+] New connection from " & clientIP & ":" & clientPort)

        Try
            Dim stream As NetworkStream = client.GetStream()
            Dim buffer(4095) As Byte

            ' Read filename from client
            Dim bytesRead As Integer = stream.Read(buffer, 0, buffer.Length)
            If bytesRead = 0 Then
                AddLog("[✗] No data received from client")
                Return
            End If

            Dim fileName As String = Encoding.UTF8.GetString(buffer, 0, bytesRead).Trim()
            AddLog("[→] Requested file: '" & fileName & "'")

            ' Security check - prevent directory traversal
            If fileName.Contains("..") OrElse fileName.StartsWith("\") OrElse fileName.StartsWith("/") Then
                SendError(stream, "Invalid file path")
                AddLog("[✗] Rejected: Invalid file path")
                Return
            End If

            ' Build full file path
            Dim fullPath As String = Path.Combine(Txt_ServerPath.Text, fileName)

            ' Check if file exists
            If Not File.Exists(fullPath) Then
                SendError(stream, "File '" & fileName & "' not found")
                AddLog("[✗] File not found: " & fileName)
                Return
            End If

            ' Read and send file content
            Dim fileContent As String = File.ReadAllText(fullPath, Encoding.UTF8)
            Dim responseData As Byte() = Encoding.UTF8.GetBytes(fileContent)

            stream.Write(responseData, 0, responseData.Length)
            AddLog("[✓] Sent " & responseData.Length & " bytes")

        Catch ex As IOException
            AddLog("[✗] File read error: " & ex.Message)
            Try
                SendError(client.GetStream(), "File is not a text file or has incompatible encoding")
            Catch
                ' Ignore if stream is already closed
            End Try
        Catch ex As Exception
            AddLog("[✗] Error handling client: " & ex.Message)
            Try
                SendError(client.GetStream(), ex.Message)
            Catch
                ' Ignore if stream is already closed
            End Try
        Finally
            client.Close()
            AddLog("[←] Connection closed: " & clientIP & ":" & clientPort)
        End Try
    End Sub

    Private Sub SendError(stream As NetworkStream, errorMessage As String)
        Dim errorMsg As String = "ERROR: " & errorMessage
        Dim errorData As Byte() = Encoding.UTF8.GetBytes(errorMsg)
        stream.Write(errorData, 0, errorData.Length)
    End Sub

    Private Sub IncrementConnectionCount()
        If Me.InvokeRequired Then
            Me.Invoke(Sub() IncrementConnectionCount())
        Else
            connectionCount += 1
            Lbl_ConnectionCount.Text = "Total Connections: " & connectionCount
        End If
    End Sub

    Private Sub UpdateUI(serverRunning As Boolean)
        If Me.InvokeRequired Then
            Me.Invoke(Sub() UpdateUI(serverRunning))
        Else
            Btn_StartServer.Enabled = Not serverRunning
            Btn_StopServer.Enabled = serverRunning
            Txt_Port.Enabled = Not serverRunning
            Txt_ServerPath.Enabled = Not serverRunning
            Btn_Browse.Enabled = Not serverRunning

            If serverRunning Then
                lblStatus.Text = "Status: RUNNING"
                lblStatus.ForeColor = Color.Green
            Else
                lblStatus.Text = "Status: STOPPED"
                lblStatus.ForeColor = Color.Red
            End If
        End If
    End Sub

    Private Sub AddLog(message As String)
        If Me.InvokeRequired Then
            Me.Invoke(Sub() AddLog(message))
        Else
            Dim timestamp As String = DateTime.Now.ToString("HH:mm:ss")
            Txt_Log.AppendText("[" & timestamp & "] " & message & vbCrLf)
            Txt_Log.SelectionStart = Txt_Log.TextLength
            Txt_Log.ScrollToCaret()
        End If
    End Sub

    Private Sub FormMain_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
        If isServerRunning Then
            Dim result As DialogResult = MessageBox.Show("Server is still running. Are you sure you want to exit?", "Confirm Exit", MessageBoxButtons.YesNo, MessageBoxIcon.Question)
            If result = DialogResult.No Then
                e.Cancel = True
                Return
            End If
            StopServer()
        End If
    End Sub
End Class