package MasterWebInterface::Handler::ServInfo;
use strict;
use warnings;
use utf8;
use TUWF ':html';
use POSIX 'strftime';
use Exporter 'import';

TUWF::register(
    qr{(.[\w]{1,20})/([\:\.\w]{9,35})} => \&show_server,
);

################################################################################
# Display server information
# Verify if game and server (ip:hostport) exist. Display as many available
# values as possible.
# Display error pages if not found or incorrect.
################################################################################
sub show_server
{
    my ($self, $gamename, $s_addr) = @_;
    
    # parse from ipv4/6 and soft sanity check
    my ($ip, $port) = $self->from_addr_str($s_addr);
    
    # select server from database
    my $info = $self->dbGetServerInfo(
        ip => $ip,
        hostport => $port,
        limit => 1,
    )->[0];
    
    # either redirect or show error when no info was found
    if (!defined $info)
    {
        # try if query port was provided instead
        my $attempt = $self->dbGetServerInfo(
            ip => $ip, 
            port => $port, 
            limit => 1
        )->[0];
        
        # if it exists now, automatically redirect to this page (don't show info here)
        if (defined $attempt && defined $attempt->{gamename} && defined $attempt->{hostport} ) 
        {
            $self->resRedirect("/$attempt->{gamename}/$ip:$attempt->{hostport}");
            return;
        }
        
        # otherwise not found in database, soft error page (no 404 status)
        $self->htmlHeader(title => 'Server not found');
        $self->htmlSearchBox(title => "Servers", action => "/s", sel => 's', fq => '');
        
        div class => "mainbox warning";
            div class => "header";
                h1 'Server not found';
                p "The requested information is not in our database.";
            end;
            
            div class => "description";
                p;
                    txt 'It seems the server you were looking for does not exist in our database,';
                    br;
                    txt 'perhaps our search function may yield results?';
                end;
                
                p;
                    txt "You tried to access ";
                    span class => "hilit", $self->to_ipv4_str($s_addr) // "[no ip]";
                    txt " in ";
                    span class => "hilit", $gamename;
                    txt ".";
                end;
            end;
        end;
        $self->htmlFooter;

        return;
    }
    
    
    #
    # info exists. sanity checks
    $gamename = $info->{gamename} // $gamename;
    my $gamedescription = $self->dbGetGameDesc($info->{gamename}) // $info->{gamename};
    
    #
    # generate info page
    $self->htmlHeader(title => $info->{hostname} // "Server");
    $self->htmlSearchBox(
        title => "$gamedescription Servers", 
        action => "/s/$gamename", 
        sel => 's', 
        fq => ''
    );
    
    # serverinfo box
    div class => "mainbox detail";
        div class => "header";
            # server data flags in header (not country flags)
            div class => "serverflags";
                
                # uplink or manually added/through applet
                if ( $info->{f_direct} ) 
                { div class => "g"; div class => "direct", title => "This server uplinks directly to $self->{site_name}.", ""; end;}
                else
                { div class => "r"; div class => "manual", title => "This server was added through master synchronisation and does not uplink to $self->{site_name}.", ""; end;}
                
                # authenticated through secure/validate
                if ( $info->{f_auth} )
                { div class => "g"; div class => "authed",   title => "This server authenticated through the secure/validate challenge.", ""; end;}
                else
                { div class => "r"; div class => "noauthed", title => "This server failed the secure/validate challenge or did not reply.", ""; end;}
                
                # server blacklisted?
                if ( $info->{f_blacklist} )
                { div class => "r"; div class => "blacklist",   title => "This server is blacklisted for violating the $self->{site_name} Terms of Use or by request from the administrator.", ""; end;}
                else
                { div class => "g"; div class => "noblacklist", title => "This server is not blacklisted by $self->{site_name}.", ""; end;}
                
                if ( $info->{passworded} and $info->{passworded} =~ /(true|1)/i )
                { div class => "r"; div class => "passwd",   title => "This server requires a password to join.", ""; end;}
                else
                { div class => "g"; div class => "nopasswd", title => "This server is accessible for everybody.", ""; end;}
            end;    
            h1 title  => $info->{hostname} // "[unnamed $gamename server]",
                         $info->{hostname} // "[unnamed $gamename server]";   
        end;
        
        #
        # Map thumbnail and bot info
        #
        div class => "container";

            # find the correct thumbnail, otherwise game default, otherwise 333 default
            div class => "thumbnail";
                my $mapfig = "/map/default/333networks.jpg";
                my $mapfile = lc ($info->{mapname} // "");
                
                # if map figure exists, use it
                if (-e "$self->{root}/s/map/$gamename/$mapfile.jpg") 
                {
                    # map image
                    $mapfig = "/map/$gamename/$mapfile.jpg";
                }
                # if not, game default image
                elsif (-e "$self->{root}/s/map/default/$gamename.jpg") 
                {
                    # game image
                    $mapfig = "/map/default/$gamename.jpg";
                }
                # otherwise 333networks default
                else
                {
                    # 333networks default
                    $mapfig = "/map/default/333networks.jpg";
                }
                
                # map title/name (not lowercase)
                my $mapname  = $info->{mapname} // $info->{maptitle} // "Untitled";
                my $maptitle = ( $info->{maptitle} && lc $info->{maptitle} ne "untitled" ) 
                             ? $info->{maptitle}
                             : $mapname;
                             
                img src => $mapfig, 
                    alt => $mapfig, 
                    title => $mapname;
                span $maptitle;
            end;
            
            # added / last seen
            div class => "updatenote";
                span title => ("Server was added on ". strftime "%e %b %Y", gmtime ($info->{dt_added} // 0) );
                    
                    txt "information updated ";
                    my @t = gmtime( time - ( $info->{dt_serverinfo} // 0 ) );

                    my $diff;
                    $diff .= ($t[5]-70)*365 + $t[7] > 0 ? ( ($t[5]-70)*365 + $t[7])." days" : "" ; # years+days
                    
                    # if no years/days, add hours/minutes/seconds to display
                    if ( ($t[5]-70)*365 + $t[7] <= 0 )
                    {
                        $diff .= ($t[2] ? $t[2]."h" : ""); # hours
                        $diff .= ($t[1] ? $t[1]."m" : ""); # minutes
                        $diff .= ($t[0] ? sprintf "%02ds", $t[0] : ""); # seconds
                    }
                    
                    # output and coloring
                    if ( length $diff )
                    {
                        span class => ( ($t[5]-70 or $t[7]) ? "r" : ($t[2] ? "o" : "g") ), $diff;
                        txt " ago.";
                    }
                    else
                    {
                        span class => "g", "right now.";
                    }
                end; #span
            end; # updatenote
        end; # container
        
        #
        # specific server entry information
        table class => "serverinfo";
            Tr; 
                th class => "wc1", title => "Server ID: " . ($info->{id} // "-1"), "Server Info"; 
                th ""; 
            end;
            
            # server address
            Tr; 
                td "Address:"; 
                td title => $info->{queryport} // 0;
                    txt $self->to_ipv4_str($info->{ip}) // "0.0.0.0";
                    txt ":";
                    txt $info->{hostport} // 0;
                end;
            end;
            
            # contact
            if ($info->{adminname}) 
            {
                Tr;
                    td "Admin:"; 
                    td $info->{adminname};
                end;
            }
            
            # always display contact
            Tr;
                td class => "wc1", "Contact:";
                td ($info->{adminemail} ? $info->{adminemail} : "-") ;
            end;
            
            # location data
            Tr;
                td class => "wc1", "Location:";
                
                my ($flag, $country) = $self->countryflag($info->{country} // "");
                td;
                    img class => "flag", src => "/flag/$flag.svg";
                    txt " ". $country;
                end;
            end;

            # numplayer field
            Tr;
                td class => "wc1", "Players:";
                td;
                    txt $info->{numplayers} // 0;
                    txt "/";
                    txt $info->{maxplayers} // 0;
                end;
            end;
            
            
            Tr;
                td "Bots:";
                td;
                if ($info->{botskill} or $info->{minplayers}) 
                {
                    txt $info->{minplayers} // 0;
                    txt " ";
                    txt $info->{botskill} // "";
                    txt " bot"; 
                    txt ($info->{minplayers} && $info->{minplayers} == 1 ? "" : "s");
                }
                else
                {
                    txt "No";
                }
                end;
            end;
            
        end; # table serverinfo
        
        #
        # Specific game and version information
        table class => "gameinfo";
            Tr; 
                th class => "wc1", "Game Info"; 
                th ""; 
            end;
            
            Tr;
                td "Game:"; 
                td;
                    a href => "/s/$gamename", $gamedescription;
                end;
            end;
            if ($info->{gametype}) 
            {
                Tr;
                    td "Type:"; 
                    td $info->{gametype};
                end;
            }
            if ($info->{gamestyle}) 
            {
                Tr;
                    td "Style:"; 
                    td $info->{gamestyle};
                end;
            }
            if ($info->{gamever}) 
            {
                Tr;
                    td "Version:"; 
                    td $info->{gamever};
                end;
            }
        end; #gameinfo
        
        #
        # Mutator list
        table class => "mutators";
            Tr;
                th "Mutators";
            end;
            Tr;
                td;
                    if (defined $info->{mutators} && $info->{mutators} ne "None") 
                    {   
                        txt $info->{mutators};
                    }
                    else 
                    {
                        i "This server does not have any mutators listed.";
                    }
                end;
            end;
        end; #mutators
        
        #
        # Player info
        table class => "players";
            my $player = $self->dbGetPlayerInfoList(sid => $info->{id});
            my %team = (0 => "#e66",
                        1 => "#66e",
                        2 => "#6e6",
                        3 => "#ee6",
                        4 => "#fe6",
                      255 => "#aaa");
        
            # iterate players and colors
            Tr; 
                th class => "wc1",   'Player Info'; 
                th class => "frags", 'Frags'; 
                th class => "mesh",  'Mesh'; 
                th class => "skin",  'Skin'; 
                th class => "ping",  'Ping'; 
            end;
            
            for (my $i = 0; defined $player->[$i]->{name}; $i++) 
            {
                # determine teamcolor
                my $teamcolor = ( defined $player->[$i]->{team} && 
                                          $player->[$i]->{team} =~ m/^([0-4]|255)$/i) 
                        ? $team{$player->[$i]->{team}} 
                        : "#aaa";
                
                Tr $i % 2 ? (class => 'odd') : (), style => 'color:'.$teamcolor;
                    td class => "wc1", title => $player->[$i]->{team} // "None";
                        txt $player->[$i]->{name} // "[no name]";
                        if ($player->[$i]->{ngsecret} && $player->[$i]->{ngsecret} =~ m/^bot$/i)
                        {
                            txt " (bot)";
                        }
                    end;
                    td class => "frags", $player->[$i]->{frags} // 0;
                    td class => "mesh",  $player->[$i]->{mesh}  // "";
                    td class => "skin",  $player->[$i]->{skin}  // "";
                    td class => "ping",  $player->[$i]->{ping}  // 0;
                end;
            }
            if ( ! defined $player->[0]->{name}) 
            {
                Tr; 
                    td colspan => 5; 
                        i "There is no player information available."; 
                    end; 
                end;
            }
        end; # playerinfo
        
        # disable stats that are considered irrelevant. can be re-enabled with "if (1)"
        if (0)
        {
        #
        # Team info
        table class => "teaminfo";
            Tr; 
                th class => "wc1", "Team Info"; 
                th ""; 
            end;
            Tr;
                td "Balance Teams:";
                td ( (defined $info->{balanceteams} && 
                              $info->{balanceteams} =~ m/true/i ) ? "Yes" : "No");
            end;
            Tr;
                td "Players Balance Teams:";
                td ( defined $info->{playersbalanceteams} && 
                             $info->{playersbalanceteams} ? "Yes" : "No");
            end;
            Tr;
                td "Friendly Fire:";
                td ($info->{friendlyfire} // "0%");
            end;
            Tr;
                td "Max Teams:";
                td ($info->{maxteams} // 1);
            end;
        end;
        
        #
        # Game Limits
        table class => "limits";
            Tr; 
                th class => "wc1", "Limits"; 
                th ""; 
            end;
            Tr;
                td "Time Limit:";
                td (($info->{timelimit} // 0). " min");
            end;
            Tr;
                td "Score Limit:";
                td ($info->{goalteamscore} // 0);
            end;
            Tr;
                td "Frag Limit:";
                td ($info->{fraglimit} // 0);
            end;
        end;
        }
        
        #
        # JSON URL (code inactive)
        table class => "shareopts";
            Tr; 
                th;
                    a href => "http://333networks.com/json", title => "For more info, click to go to 333networks.com/json", "Json API";
                end;
            end;
            td ($self->{site_url} . "/json/" . $gamename . "/" . ( $self->to_ipv4_str($info->{ip}) // "0.0.0.0" ) . ":" . ($info->{hostport} // 0));
        end;
      
    end; # mainbox details
    $self->htmlFooter;
}

1;
