#!/usr/bin/perl
use strict;
use warnings;

use lib 'lib';
use LightTCP::Server;

my $port = $ARGV[0] || 7002;
my $upload_dir = "/tmp/demo_uploads";

print "Starting OOP demo server on port $port...\n";

if (!-d $upload_dir) {
    mkdir($upload_dir, 0755) or die "Cannot create upload directory: $!";
}

my $server = LightTCP::Server->new(
    server_addr    => "0.0.0.0:$port",
    server_name    => 'OOPDemoServer',
    server_type    => 'thread',
    max_threads    => 5,
    server_timeout => 10,
    server_perlonly=> 1,
    verbose        => 2,
    logfn          => 'demo_oo_server',

    upload_dir          => $upload_dir,
    upload_max_size     => 25 * 1024 * 1024,
    func_upload         => \&handle_upload,

    rate_limit_enabled      => 1,
    rate_limit_requests     => 50,
    rate_limit_window       => 60,
    rate_limit_block_duration => 300,
    rate_limit_whitelist    => [qw(127.0.0.1 ::1 localhost)],

    func_timeout   => \&handle_timeout,
    func_perl      => \&handle_request,
    func_log       => \&handle_log,
    func_done      => \&handle_done,
);

print "\n";
print "=" x 70 . "\n";
print "  OOP Demo Server with File Upload & Rate Limiting\n";
print "=" x 70 . "\n";
print "  Port              : $port\n";
print "  Type              : Threaded (max 5 threads)\n";
print "  Upload Dir        : $upload_dir\n";
print "  Max Upload Size   : 25 MB\n";
print "  Rate Limit        : 50 requests per 60 seconds\n";
print "  Block Duration    : 5 minutes\n";
print "-" x 70 . "\n";
print "  Endpoints:\n";
print "    /              - Home page\n";
print "    /json          - JSON API response\n";
print "    /status        - Server status\n";
print "    /stop          - Stop the server\n";
print "    /echo          - Echo query parameters\n";
print "    /upload        - File upload form (GET)\n";
print "    /upload        - File upload handler (POST)\n";
print "    /rate-limit-test - Test rate limiting\n";
print "-" x 70 . "\n";
print "\n";

print "Server instance created. Starting...\n";
my $result = $server->start();
print "Server stopped with result: $result\n";
exit 0;

sub handle_upload {
    my ($self, $uploads) = @_;

    my @results;
    for my $upload (@$uploads) {
        if ($upload->{success}) {
            $self->logit("# Upload success: $upload->{filename} ($upload->{size} bytes)");
            push @results, "$upload->{filename} saved to $upload->{saved_path}";
        } else {
            $self->logit("# Upload failed: $upload->{filename} - $upload->{error}");
            push @results, "ERROR: $upload->{filename} - $upload->{error}";
        }
    }

    my $body = "Upload Results:\n\n" . join("\n", @results);
    return (201, $body);
}

sub handle_timeout {
    my ($self) = @_;
    $self->logit("# Server timeout occurred after " . $self->server_timeout . " seconds", 0);
    $self->{server_timeout}+=$self->{server_timeout};
}

sub handle_request {
    my ($self, $client, $preq) = @_;

    my $method = $preq->{METHOD} || 'GET';
    my $uri = $preq->{URI} || '/';
    my $clip = $preq->{clip} || 'unknown';

    my $response_body;
    my $content_type = 'text/plain';
    my $status = '200 OK';

    if ($uri eq '/' || $uri eq '/index') {
        $response_body = <<"HTML";
<!DOCTYPE html>
<html>
<head><title>LightTCP Demo Server</title></head>
<body>
<h1>LightTCP Demo Server</h1>
<p>Welcome to the LightTCP demo!</p>
<p>Server: OOPDemoServer</p>
<p>Port: $port</p>
<p>Time: """ . localtime() . """</p>
<p>Your IP: $clip</p>
<p>Request: $method $uri</p>
<hr>
<h2>Available Endpoints</h2>
<ul>
<li><a href="/">Home</a></li>
<li><a href="/json">JSON API</a></li>
<li><a href="/status">Status</a></li>
<li><a href="/upload">Upload Form</a></li>
<li><a href="/echo?test=hello">Echo Test</a></li>
<li><a href="/rate-limit-test">Rate Limit Test</a></li>
</ul>
<hr>
<p>This response is generated by a Perl class using pure Perl OOP.</p>
</body>
</html>
HTML
        $content_type = 'text/html';
    } elsif ($uri eq '/json') {
        $response_body = sprintf '{"status":"ok","server":"OOPDemoServer","port":%d,"time":"%s","client":"%s"}',
            $port, localtime(), $clip;
        $content_type = 'application/json';
    } elsif ($uri eq '/status') {
        my $running = $self->is_running() ? 'running' : 'stopped';
        my $upload_dir = $self->upload_dir;
        my $upload_count = 0;
        $upload_count = scalar(glob("$upload_dir/*")) if -d $upload_dir;

        $response_body = "Server Status: $running\n";
        $response_body .= "Server Name: " . $self->server_name . "\n";
        $response_body .= "Server Addr: " . $self->server_addr . "\n";
        $response_body .= "Server Type: " . $self->server_type . "\n";
        $response_body .= "Max Threads: " . $self->max_threads . "\n";
        $response_body .= "Verbose Level: " . $self->verbose . "\n";
        $response_body .= "Uploads Directory: $upload_dir\n";
        $response_body .= "Upload Files: $upload_count\n";
        $response_body .= "Rate Limiting: " . ($self->rate_limit_enabled ? 'enabled' : 'disabled') . "\n";
        if ($self->rate_limit_enabled) {
            $response_body .= "Rate Limit: " . $self->rate_limit_requests . " req/" . $self->rate_limit_window . "s\n";
            $response_body .= "Block Duration: " . $self->rate_limit_block_duration . "s\n";
        }
        $content_type = 'text/plain';
    } elsif ($uri eq '/stop') {
        $response_body = "Stopping server...";
        $status = '200 OK';
        $self->stop();
    } elsif ($uri eq '/echo') {
        my $params = $preq->{QUERY_STRING} || '';
        $response_body = "Echo: $params";
        $content_type = 'text/plain';
    } elsif ($uri eq '/rate-limit-test') {
        $response_body = <<"HTML";
<!DOCTYPE html>
<html>
<head><title>Rate Limit Test</title></head>
<body>
<h1>Rate Limit Test</h1>
<p>This page will make multiple requests to test rate limiting.</p>
<p>Limit: """ . $self->rate_limit_requests . """ requests per """ . $self->rate_limit_window . """ seconds</p>
<p>Click the button to start testing:</p>
<button onclick="testRateLimit()">Start Test</button>
<div id="results"></div>
<script>
let count = 0;
function testRateLimit() {
    fetch('/echo?test=' + count)
        .then(r => r.text())
        .then(t => {
            count++;
            document.getElementById('results').innerHTML += '<p>Request ' + count + ': ' + t.substring(0, 50) + '</p>';
            if (count < 60) setTimeout(testRateLimit, 100);
        });
}
</script>
</body>
</html>
HTML
        $content_type = 'text/html';
    } else {
        $response_body = "Error 404: Not Found\nURI: $uri";
        $status = '404 Not Found';
        $content_type = 'text/plain';
    }

    my $len = length($response_body);

    $self->logit("# Handling request from $clip - $method $uri");

    my @headers = (
        "HTTP/1.1 $status",
        "Server: " . $self->server_name,
        "Content-Type: $content_type",
        "Content-Length: $len",
        "Connection: close"
    );

    if ($uri eq '/json') {
        push @headers, "Access-Control-Allow-Origin: *";
    }

    eval {
        local $SIG{PIPE} = sub { die "Broken pipe\n" };
        print $client join("\r\n", @headers) . "\r\n\r\n" . $response_body;
    };

    if ($@) {
        $self->logit("# Error sending response: $@");
    }

    return ($status =~ /^(\d+)/ ? $1 : 500, $len);
}

sub handle_log {
    my ($self, $msg, $lvl) = @_;

    $lvl = 2 if !defined $lvl || $lvl eq '';
    return if $lvl > $self->verbose;

    my $base_logfn = $self->logfn;
    my ($timestr, $now) = $self->_gettime();

    if ($base_logfn ne '') {
        my ($sec, $min, $hour, $mday, $mon, $year, $wday) = localtime($now);
        my $logfn = $base_logfn . '_' . $wday . '.log';

        if (-f $logfn) {
            my $mtime = (stat($logfn))[9];
            if (($mtime + 86400) < $now) {
                unlink $logfn or warn "Cannot delete outdated log $logfn: $!";
            }
        }

        if (open(my $fp, '>>', $logfn)) {
            $timestr =~ s/-//g;
            print $fp substr($timestr, 2) . " $msg\n";
            close($fp);
        }
    }

    $timestr =~ s/[-:]//g;
    if (substr($msg, 0, 1) eq '#') {
        printf STDERR "# %s %s\n", substr($timestr, -11), substr($msg, 2);
    } elsif ($self->verbose) {
        printf STDERR "- %s %s\n", substr($timestr, -11), $msg;
    }
}

sub handle_done {
    my ($self, $preq) = @_;
    $self->logit("# Request completed for $preq->{URI}");
}


__END__

=head1 NAME

demo.pl - Demo server using LightTCP::Server pure Perl OOP module

=head1 SYNOPSIS

    perl examples/demo.pl [port]

=head1 DESCRIPTION

This demo script demonstrates the OOP interface of the LightTCP::Server module.
It creates a threaded server with file upload and rate limiting features.

=head1 FEATURES

=over 4

=item * Threaded operation (max 5 threads)

=item * File Upload Support:
  - POST to /upload to upload files
  - GET /upload shows upload form
  - Max upload size: 25 MB
  - Automatic filename sanitization
  - Atomic file writing

=item * Rate Limiting:
  - 50 requests per 60 seconds per IP
  - 5 minute block for exceeded limits
  - Whitelist for localhost/bypass

=item * Multiple endpoints:
  - / - HTML home page
  - /json - JSON API response
  - /status - Server status
  - /stop - Stop the server
  - /echo - Echo query parameters
  - /upload - File upload form/handler
  - /rate-limit-test - Rate limit testing page

=item * Custom logging with daily rotation

=item * Timeout handling

=back

=head1 DATE

Last updated: January 2026

=cut
