use strict;

# structural preparation =======================================================
sub ET2
{
    my ($node, $et) = @_;
    $_ = $node->{'path'};

# sections: nesting and titles ----------------------------------------------
    # ensure correct nesting of sections
    m<^/div_sect0/$> ||
    m</div_sect(0/div_sect1|1/div_sect2|2/div_sect3)/$> ||
    m</div_sect[0123]/div_(figure|example|table)/$> and do {
        die $node->Tx( "%f no label for %p\n " ) 
            if( !defined $node->{'attr'}{'name'} );
        Diag( $node->Tx( "%f Processing $node->{'attr'}{'name'}" ) )
            if( $_ =~ /_sect[01]\/$/ );
        return $node->Proc( $et );
    };
    
    # the correct H tag is only once
    m</div_(sect(0/h1|1/h2|2/h3|3/h4)|(figure|example|table)/h4)/$> && do {
        die $node->Tx( "%f superfluous %p\n " ) 
            if( defined $node->{'parent'}{'caption'} );
        $node->{'parent'}{'caption'} = $node;
        return $node->Proc( $et );
    };

    # the H tag is the first
    m</div_(sect[123]|figure|example)/(\w+)/$> && 
                   ! defined( $node->{'parent'}{'caption'} ) &&
        die $node->Tx( "%f the first div element cannot be %p\n " );

    # proces A_TITLE
    m</div_(sect[0123]|example|figure|table)/h[1234]/a_title/$> && 
        return( $node->Proc( \&ET2_IWA )->{'content'} );  # flatten

# sections: other content ---------------------------------------------------
    # table - sub ET
    m</div_table/table/$> &&
        return $node->Proc( \&ET2_T, 'path' => 'T/' ); # process in new context
    
    # programlisting
    m</div_(example|sect[0123])/div_programlisting/$> && 
        return $node->Proc( $et );

    m</div_programlisting/pre/$> && 
        return $node->Proc( \&ET2_IWA )->{'content'};

    # figures
    m</div_figure/p/$> && return $node->Proc( $et )->{'content'};
    m</div_figure/p/img/$> && return $node;

    # par
    m</div_(sect[0123]|literallayout)/p/$> && return $node->Proc( \&ET2_I );

    # lists
    m</(div_sect[0123]|li)/[uod]l/$> && return List( $node );

    # footnotes
    # (div/p/a_footnote is inline)

    m</div_sect[0123]/blockquote_footnote/$> && do
    {
        my $id = "#" . $node->{'attr'}{'name'};
        die $node->Tx( "%f not requested %p\n " )
            if( ! defined( $node->{'root'}{'fnote'}{ $id } ) );
        $node->Proc( \&ET2_I );
        $node->{'root'}{'fnote'}{ $id }{'content'} = $node->{'content'};
        delete( $node->{'root'}{'fnote'}{ $id } );
        return 0;
    };

    die $node->Tx( "%f unhandled %p\n " );
}

# tables =======================================================================
sub ET2_T # table ET
{
    my ($node, $et) = @_;
    $_ = $node->{'path'};

    # caption move to div as h4
    m<^T/caption/$> && do {
        $node->{'tag'} = 'h4';
        $node->{'parent'}{'parent'}->AddFirst( $node );
        ET2( $node, \&ET2 );
        return 0;
    };

    # caption must be first
    m<^T/(\w+)/$> && ! defined $node->{'parent'}{'parent'}{'caption'} &&
        die $node->Tx( "%f the first table element cannot be %p\n " );
 
    # data
    m<^T/tr/$> && return $node->Proc( $et );

    m<^T/tr/th/$> and $node->{'parent'}{'tag'} ne 'trd' and do {
        $node->{'parent'}{'tag'} = 'trh';
        return $node->Proc( \&ET2_I );
    };

    m<^T/tr/td/$> and $node->{'parent'}{'tag'} ne 'trh' and do {
        $node->{'parent'}{'tag'} = 'trd';
        return $node->Proc( $et );
    };

    m<^T/tr/td/p/$> && do {
        Diag( $node->Tx( "%f strange %p" ) );
        return $node->Proc( \&ET2_I );
    };

    m<^T/tr/td/div_programlisting/$> && do {
        Diag( $node->Tx( "%f strange %p" ) );
        return $node->Proc( \&ET2 );
    };

    m<^T/tr/td/blockquote_/$> && do {
        Diag( $node->Tx( "%f flattened %p" ), 'i' );
        return $node->Proc( $et )->{'content'};
    };

    m<^T/tr/td/blockquote_/p/$> &&
        return $node->Proc( \&ET2_I );

    m<^T/tr/td/\w+/$> && return ET2_I( $node, \&ET2_I );

    die $node->Tx( "%f unhandled %p\n " );
}

# list content =================================================================
sub List
{
    my $node = shift;

    $node->{'last'} = '';
    $node->Proc( \&ET2_L );
    die $node->Tx( "%f dt/dd must be in pairs %p\n " ) 
        if( $node->{'last'} eq 'dt' );
    return $node;
}

sub ET2_L
{
    my ($node, $et) = @_;
    $_ = $node->{'path'};

    m</[uo]l/li/$> && return $node->Proc( $et );
    m</dl/(dt|dd)/$> && $node->{'parent'}{'last'} ne $1 && do {
        $node->{'parent'}{'last'} = $1;
        return $node->Proc( $1 eq 'dt' ? \&ET2_I : $et );
    };

    m</(dd|li)/p/$> && return $node->Proc( \&ET2_I );
    m</(dd|li)/div_programlisting/$> && return $node->Proc( \&ET2 );
    m</li/[uod]l/$> && return List( $node );

    die $node->Tx( "%f unhandled %p\n " );
}

# inline ET, can contain a =====================================================
sub ET2_I 
{
    my ($node, $et) = @_;
    $_ = $node->{'tag'};

    m<^(tt|i|b|br|TEXT(_S)?)$> && return $node->Proc( $et ); # nesting inline
    m<^a_(fig|ex|tab|ch|app|ref)$> && return $node->Proc( \&ET2_IWA ); # a
    m<^a_footnote$> && do
    {
        return 0 if( $node->{'attr'}{'name'} );
        die $node->Tx( "%f twice requested %p\n " )
            if( defined( $node->{'root'}{'fnote'}{ $node->{'attr'}{'href'} } ));

        $node->{'root'}{'fnote'}{$node->{'attr'}{'href'}} = $node;
        $node->{'content'} = [];
        return $node;
    };

    $_ = $node->{'path'};

    die $node->Tx( "%f unhandled %p\n " );
}

# inline ET without a ==========================================================
sub ET2_IWA 
{
    my ($node, $et) = @_;

# nesting inline elements
    $node->{'tag'} =~ /^(tt|i|b|br|TEXT(_S)?)$/ && return $node->Proc( $et );

    die $node->Tx( "%f unhandled %p\n " );
}

# basic preparation - plusclass, throw some elements
sub ET2_pre
{
    my ($node, $et) = @_;
    $_ = $node->{'path'};

    # add class to the tagname and return to process again (caller updates path)
    m</(div|a|blockquote|span)/$> && do {
        $node->{ 'tag' } .= '_' . ( lc($node->{'attr'}->{'class'}) || '' );
        return 'redo';
    };

    # nodes to skip - void texts, nav, secnum
    m<^/TEXT_S/$> && return 0; 
    m</div_(sect[0123]|figure|example|table|programlisting)/TEXT_S/$> && 
        return( 0 ); 
    m</div_figure/p/TEXT_S/$> && return 0;

    m</div_literallayout/TEXT_S/$> && return 0;
    m</blockquote_footnote/TEXT_S/$> && return 0;
    m</blockquote_/TEXT_S/$> && return 0;
    m</[uod]l(/li|/dd|/dt)?/TEXT_S/$> &&  return 0;
    m<^/div_nav/$> && return 0;
    m</a_title/span_secnum/$> && return 0;
    m</table(/tr)?/TEXT_S/$> && return 0; 

    # nodes to flatten
    m</div_literallayout/$> && return $node->Proc( $et )->{'content'};
    m</div_note/$> && do {
        Diag( $node->Tx( "warn:%f flattened %p" ), 'w' );
        return $node->Proc( $et )->{'content'};
    };
    m</div_note/blockquote_/$> && return $node->Proc( $et )->{'content'};
    m</div_note/TEXT_S/$> && return 0;

    return $node->Proc( $et );
}


1;
