#
#   OpenLyrics - open internet lyrics database
#
#   Copyright (C) 2003 Mark A. Stratman
#
#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; either version 2 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program; if not, write to the Free Software
#   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#

#
#   $Id: FAQ.pm,v 1.2 2004/03/22 08:16:26 sporkstorms Exp $
#   FAQ, FAQ::Question, FAQ::Section - friendly OO wrappers for dealing
#   with the FAQ data
#

package FAQ;

use strict;
use warnings;
use XML::Twig;
use base qw(Class::Accessor::Fast);
__PACKAGE__->mk_accessors(qw(questions sections items file));

our $VERSION = sprintf("%d.%02d", q$Revision: 1.2 $ =~ /: (\d+)\.(\d+)/);

# args for new()
# new({ file => $filename, htmlify => 1 });

sub htmlify
{
    my $self = shift;
    my $what = shift;
    return '' unless $what;
    $what =~ s/&/&amp;/g;
    $what =~ s/</&lt;/g;
    $what =~ s/>/&gt;/g;
    $what =~ s/"/&quot;/g;
    return $what;
}

# $faq->write_file() or die; # using the filename you specified in new()
# $faq->write_file($filename) or die;
sub write_file
{
    my $self = shift;
    my $fn = shift || $self->file();
    return undef unless defined $fn && -e $fn;
    # TODO - finish this
}

# $faq = FAQ->new(); $faq->read_file($filename) or die;
# $faq = FAQ->new({ file => $filename }); $faq->read_file() or die;
sub read_file
{
    my $self = shift;
    unless (ref $self && UNIVERSAL::isa($self, 'FAQ')) {
        $self = FAQ->new();
    }
    my $fn = shift || $self->file();
    return undef unless defined $fn && -e $fn;
    $self->file($fn);
    my $twig = XML::Twig->new();
    $twig->safe_parsefile($fn) or return undef;
    my @sections = ();
    my @questions = ();
    my @items = ();
    my $faq = $twig->root();
    my $href = 1;
    for ($faq->children()) {
        if ($_->gi() eq 'section') {
            my $section = FAQ::Section->from_xml($_,
                { href => $href++, htmlify => $self->{htmlify} });
            return undef unless $section;
            $section->parent_section(undef);
            push @sections, $section;
            push @items, $section;
        } elsif ($_->gi() eq 'question') {
            my $question = FAQ::Question->from_xml($_,
                { href => $href++, htmlify => $self->{htmlify} });
            return undef unless $question;
            $question->parent_section(undef);
            push @questions, $question;
            push @items, $question;
        }
    }
    $self->questions(\@questions);
    $self->sections(\@sections);
    $self->items(\@items);
    return $self;
}

#
# FAQ::Question
#
package FAQ::Question;
use base qw(Class::Accessor::Fast);
__PACKAGE__->mk_accessors(qw(label answer parent_section href));

sub question { my $self = shift; return $self->label(@_) }
sub has_parent { return $_[0]->parent_section() ? 1 : 0 }

# Two convenient methods for templates to use
sub is_section  { return 0 }
sub is_question { return 1 }

sub from_xml
{
    my $package = shift;
    my $gi = shift;
    my $vars = shift;
    my $self = FAQ::Question->new();
    if ($vars && ref $vars) {
        $self->{$_} = $vars->{$_} for keys %$vars;
    }
    my $label = $gi->att('label');
    return undef unless defined $label;
    $label = FAQ->htmlify($label) if $self->{htmlify};
    $self->label($label);
    my $answer = $gi->trimmed_text();
    $answer = FAQ->htmlify($answer) if $self->{htmlify};
    $self->answer($answer);
    return $self;
}


#
# FAQ::Section
#
package FAQ::Section;
use base qw(Class::Accessor::Fast);
__PACKAGE__->mk_accessors(qw(label sections questions items
    parent_section href));

sub has_parent { return $_[0]->parent_section() ? 1 : 0 }

# Two convenient methods for templates to use
sub is_section  { return 1 }
sub is_question { return 0 }

sub from_xml
{
    my $package = shift;
    my $gi = shift;
    my $vars = shift;
    my $self = FAQ::Section->new();
    if ($vars && ref $vars) {
        $self->{$_} = $vars->{$_} for keys %$vars;
    }
    my $label = $gi->att('label');
    return undef unless defined $label;
    $label = FAQ->htmlify($label) if $self->{htmlify};
    $self->label($label);
    my @sections = ();
    my @questions = ();
    my @items = ();
    my $href = 1;
    for ($gi->children()) {
        if ($_->gi() eq 'section') {
            my $s = FAQ::Section->from_xml($_,
                { href => $self->href() . '_' . $href++,
                  htmlify => $self->{htmlify} });
            $s->parent_section($self);
            push @sections, $s;
            push @items, $s;
        } elsif ($_->gi() eq 'question') {
            my $q = FAQ::Question->from_xml($_,
                { htmlify => $self->{htmlify} });
            $q->parent_section($self);
            $q->href($self->href() . '_' . $href++);
            push @questions, $q;
            push @items, $q;
        }
    }
    $self->sections(\@sections);
    $self->questions(\@questions);
    $self->items(\@items);
    return $self;
}

1;
__END__
# Below is stub documentation for your module. You better edit it!

=head1 NAME

FAQ - Perl extension for blah blah blah

=head1 SYNOPSIS

  use FAQ;
  blah blah blah

=head1 DESCRIPTION

Stub documentation for FAQ, created by h2xs. It looks like the
author of the extension was negligent enough to leave the stub
unedited.

Blah blah blah.

=head2 EXPORT

None by default.

=head1 METHODS

=over 4

=item foo

=back

=head1 AUTHOR

Mark A. Stratman E<lt>mark@sporkstorms.orgE<gt>

=head1 SEE ALSO

L<perl>.

=cut

