#!/usr/bin/perl -wT

use strict;
use lib '.';
use Dev2;
use CGI;
my $q = new CGI;

my $jump = $q->param('jump') || '';
if ($jump) {
  print	$q->redirect($q->url( -base => 1 ) . $q->url( -absolute => 1 ) . $jump);
  exit;
}

# Relies on this scrip being called 'contrib' and it 'contrib.css'.
my $css = $q->url( -base => 1 ) . $q->script_name() . '.css';

my $index_name = '00Index';
my $ftp_root = '/home/ftp/pub/CircleMUD/contrib';
my $download_root = 'http://www.circlemud.org/pub/CircleMUD/contrib';

my $path_info = $q->path_info() || '/';
$path_info =~ tr/.//s;

if (! -e "$ftp_root$path_info") {
  print	$q->header( -status => 404 ),
	$q->start_html,
	$q->p("No such location: $path_info"),
	$q->end_html;
  exit;
}

# Mimick Apache behavior of redirect "/dir" -> "/dir/"
if (-d "$ftp_root$path_info" && not $path_info =~ m!/$!) {
  print $q->redirect($q->url . '/');
  exit;
}

# Did we request a file or a directory listing?
my $request = "$ftp_root$path_info";
my $request_file = (-f $request);

# Find our 00Index for this directory, if it exists.
my $index = '';
if (!$request_file) {
  if (-e "$request$index_name") {
    $index = "$request$index_name";
  }
} else {
  # Hmm, we have a file URI, whack the filename for the directory.
  my $directory = $request;
  $directory =~ s![^/]+$!!;
  $directory .= $index_name;
  if (-e $directory) {
    $index = $directory;
  }
}

my $index_hash;
if (!$index) {
  warn "No $index_name for $request\n";
  $index_hash = {};
} else {
  $index_hash = Dev2::parse_index($index_name, $index);
}

if ($request_file) {
  list_file($path_info, $request, $index_hash);
} else {
  list_directory($path_info, $request, $index_hash);
}

exit;

# -----

sub list_directory # ($$\%)
{
  my ($webdir, $dir, $index) = @_;
  my %index = %{$index};
  my @colors = qw(dir-listing-bg1 dir-listing-bg2);

  if (!opendir(DIR, $dir)) {
    warn "$dir: $!\n";

    print $q->header( -status => 403 ),
	$q->start_html( -title => 'Permission denied' ),
	$q->p("$dir cannot be accessed."),
	$q->end_html;
    exit;
  }

  $dir =~ m!^(.*/)([^/]+/)$!;
  my ($parent, $dirname) = ($1, $2);
  my $parent_index = Dev2::parse_index($index_name, "$parent$index_name");
  my $this_dir_name = $dirname && $parent_index ? $parent_index->{$dirname} : '';

  print	$q->header,
	$q->start_html( -title => "CircleMUD Contributions: $webdir", -style => { -src => $css } ),
	$q->p({ -class => 'contrib-title' }, q(CircleMUD Developer's Resources)),
	$q->p($q->b($webdir) . ($this_dir_name ? ": $this_dir_name" : ''));

  if (-e "$dir.message" && open(MESG, "<$dir.message")) {
    my $text = '';
    $text .= $_ while (<MESG>);
    close(MESG);
    print $q->pre($text);
  }

  my $up = $q->url . $webdir;
  $up =~ s![^/]+/$!!;

  my $color = 0;
  print	$q->start_table({ -width => '100%' }),
	$q->Tr([
		$q->th({ -class => 'dir-header-bg' }, [
			map { $q->span({ -class => 'dir-header-fg' }, $_) } ('Name', 'Description', 'Size', 'Date')
		]),
		$q->td({ -class => $colors[$color++ % @colors] }, [
			map { $q->span({ -class => 'dir-listing-fg' }, $_) }
				($q->a({ -href => '/' }, '[Home]'), 'Back to main page', '&nbsp;', '&nbsp;')
		]),
		$q->td({ -class => $colors[$color++ % @colors] }, [
			map { $q->span({ -class => 'dir-listing-fg' }, $_) }
				($q->a({ -href => $up }, '..'), 'Up to parent directory', '&nbsp;', '&nbsp;')
		]),
	]);

  my (@file, @dirs);
  foreach my $entry (readdir(DIR)) {
    next if (-l "$dir$entry");
    next if ($entry eq $index_name);
    next if ($entry =~ /\.README$/);
    next if ($entry =~ /^\./);

    push(@file, $entry) if (-f _);
    push(@dirs, $entry) if (-d _);
  }
  closedir(DIR);

  foreach my $file (sort(@dirs), sort(@file)) {
    my $mtime = (stat("$dir$file"))[9];

    my ($day, $month, $year) = (localtime($mtime))[3,4,5];
    $month = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec')[$month];
    $year += 1900;

    my $line_class = $colors[$color++ % @colors];
    print $q->Tr([
	$q->td({ -valign => 'top', -align=> 'left', -class => $line_class }, [
		$q->a({ -href => ($q->url . $webdir . $file . (-d _ ? '/' : '')) }, $file),
		$index{$file . (-d _ ? '/' : '')} || 'No description available.'
		]) .
	$q->td({ -valign => 'top', -align => 'right', -class => $line_class }, [
		-d _ ? '&nbsp;' : Dev2::commify(-s _),
		"$month&nbsp;$day,&nbsp;$year"
	]) ]);
  }

  print $q->end_table,
	Dev2::directory_pulldown($q, $webdir),
	$q->end_html;
}

# -----

sub list_file # ($$\%)
{
  my ($webfile, $file, $index) = @_;
  my %index = %{$index};

  my $readme = '';
  if (-e "$file.README") {
    $readme = "$file.README";
  } else {
    my $lopfile = $file;
    $lopfile =~ s/[^.]+$/README/;
    if (-e $lopfile) {
      $readme = $lopfile;
    }
  }

  my $readme_text = '';
  if ($readme && open(README, "<$readme")) {
    $readme_text .= $_ while(<README>);
    close(README);
  }

  $webfile =~ m!^(.*/)([^/]+)$!;
  my ($webdir, $filename) = ($1, $2);
  if (!$webdir || !$filename) {
    warn "No webdir/filename: $webfile\n";
  }

  my $readme_filename = '';
  if ($readme) {
    $readme =~ m!/([^/]+)$!;
    $readme_filename = $1;
  }

  print	$q->header,
	$q->start_html( -title => "CircleMUD Contributions: $webfile", -style => { -src => $css } ),
	$q->p({ -class => 'contrib-title' }, q(CircleMUD Developer's Resources)),
	$q->table({ -width => '100%' }, [ $q->Tr([
		$q->td([ 'Name:', $q->a({ -href => ($download_root . $webfile) }, $filename) ]),
		$q->td([ 'Size:', Dev2::commify(-s $file) . ' bytes' ]),
		$q->td([ 'Date:', scalar localtime((stat $file)[9]) ]),
		$q->td([ 'Brief description:', $index{$filename} || 'Not available.' ]),
		$q->td([ 'Documentation:', $readme ?
			$q->a({ -href => ($download_root . $webdir . $readme_filename) }, $readme_filename) : 'None.' ]),
		$q->td({ -colspan => 2 }, [ $readme_text ? $q->pre($readme_text) : '---' ]),
	]) ]);

  my @files = sort keys %index;
  my $this_index;
  for ($this_index = 0; $this_index <= $#files; $this_index++) {
    last if ($files[$this_index] ge $filename);
  }
  my ($left, $right);
  if ($this_index > $#files) {
    $left = '';
  } elsif ($files[$this_index] ne $filename) {
    # Not found, point at this entry, where it should be.
    $left = $files[$this_index];
  } elsif ($this_index > 0) {
    $left = $files[$this_index - 1];
  } else {
    $left = '';
  }
  $right = $this_index < $#files ? $files[$this_index + 1] : '';

  my @jump_file = map { $webdir . $_ } (@files);
  my %jump_maps;
  for (my $x = 0; $x <= $#files; $x++) {
    $jump_maps{$jump_file[$x]} = $files[$x];
  }

  print	$q->table({ -width => '100%' }, [ $q->Tr([
		$q->td({ -align => 'left' }, [ 'Previous: ' . ($left ?
			$q->a({ -href => ($q->url . $webdir . $left) }, $left) : 'None') ]) .
		$q->td({ -align => 'center' }, [ $q->a({ -href => ($q->url . $webdir) }, 'Back to Directory') ]) .
		$q->td({ -align => 'center' }, [ $q->a({ -href => '/' }, 'Main page') ]) .
		$q->td({ -align => 'right' }, [ 'Next: ' . ($right ?
			$q->a({ -href => ($q->url . $webdir . $right) }, $right) : 'None') ])
	]) ]),

	$q->table({ -width => '100%' }, [ $q->Tr([
		$q->td([ join('',
			$q->start_form( -method => 'GET', -action => $q->url( -absolute => 1 ) ),
			$q->popup_menu( -name => 'jump', -values => \@jump_file, -labels => \%jump_maps, -default => $jump_file[$this_index] ),
			$q->submit( -value => 'Jump' ),
			$q->end_form),

			Dev2::directory_pulldown($q, $webdir)
		])
	]) ]),

	$q->end_html;
}
