package List::Index;

use 5.010;
use strict;
use warnings;

our $VERSION = '1.00';

sub new {
	my ($class, $values) = @_;
	bless [sort map { s/[^a-z]/./g; $_ } @$values], $class;
}

sub ranges {
	my $self = shift;
	my $options = shift || {};
	my $pagesize = $options->{pagesize} || 50;
	my $context  = $options->{context } // 1 + ($pagesize >> 4);
	my $length   = $options->{length  } || 4;
	my $pages    = $options->{pages   } || 1 + int $#$self / $pagesize;

	$pagesize = @$self / $pages;
	my $offset = 0;
	my @links;
	while ($offset < @$self) {
		my $link = substr $self->[$offset], 0, $length;
		if ($context) {
			my $trim = 1;
			my $before = $offset > $context ? $self->[$offset - $context] : '';
			for my $match (split //, $before) {
				scalar $link =~ /\G\Q$match/g or last;
				$trim++;
			}
			substr($link, $trim) = '' unless $trim > length $link;
		}

		push @links, [$link];
		$offset += $pagesize;
	}

	for my $i (0 .. $#links - 1) {
		my ($link, $lastchar) = $links[$i + 1]->[0] =~ /(.*)(.)/;
		$link .= $lastchar eq '.' ? 'z' : chr( ord($lastchar) - 1 )
			unless $lastchar eq 'a';
		$links[$i]->[1] = $link;
	}
	$links[-1]->[1] = '';

	return \@links;
}

1;

__END__

=head1 NAME

List::Index - Paginate alphabetic entries by finding minimal prefixes

=head1 SYNOPSIS

	use List::Index;
	my $index = List::Index->new(\@values);
	my @pages = $index->ranges({pagesize => 50});
	printf '<a href="?start=%s&amp;end=%s">%1$s</a> ', @$_ for @pages;

=head1 DESCRIPTION

TODO

=head1 SEE ALSO

L<List::Maker|List::Maker> for complex ranges of numeric lists.

=head1 AUTHOR

Mischa POSLAWSKY <perl@shiar.org>

=head1 LICENSE

Copyright. All rights reserved.

