package Lorem::Element::Text;
{
  $Lorem::Element::Text::VERSION = '0.21';
}

use Moose;
use MooseX::SemiAffordanceAccessor;
use MooseX::StrictConstructor;

with 'MooseX::Clone';

use Cairo;
use Pango;

extends 'Lorem::Element::Inline';

has '+parent' => (
    required => 0,
);

has 'content' => (
    is  => 'rw',
    isa => 'Str',
    default => '',
    trigger => sub {
        return if ! $_[0]->_has_layout;
        $_[0]->_layout->set_markup( $_[1] );
    }
);

has '_layout' => (
    is => 'rw',
    isa => 'Object',
    lazy_build => 1,
    reader => '_get_layout',
    writer => '_set_layout',
    predicate => '_has_layout',
);

sub _on_set_parent {
    my $self = shift;
}

sub _layout {
    my ( $self, $cr ) = @_;
    $self->_set_layout( $self->_build__layout( $cr ) ) if ! $self->_has_layout;
    return $self->_get_layout;
}

sub _build__layout {
    my ( $self, $cr ) = @_;
    my $layout = Pango::Cairo::create_layout( $cr );
    $self->_set_layout( $layout );
    
    # parse markup
    my ( $newatts, $text) = Pango->parse_markup( $self->content );
    $layout->set_text( $text );
    
    # apply style (with additional attributes from markup)
    $self->_apply_style_to_layout( $newatts ); # must happen before parsing markup
    
    return $layout;
}

sub imprint {
    my ( $self, $cr ) = @_;
    confess "must pass a context to 'imprint'" if ! $cr;
    
    my $allocated = $self->size_allocation;
    
    my $layout = $self->_layout( $cr );
    #$layout->set_width( $allocated->{width} * Pango->scale );
    $cr->move_to ( $allocated->{x}, $allocated->{y} );
    Pango::Cairo::show_layout( $cr, $layout );
}

sub size_request {
    my ( $self, $cr, $w ) = @_;
    
    my $layout = $self->_layout ( $cr );
    
    my $te = $layout->get_extents;
    # my $w  = defined $self->width  ? $self->width  : defined $self->parent->inner_width ? $self->parent->inner_width : $te->{width} / Pango->scale;
    
    if ( ! defined $w ) {
        if ( defined $self->width ) {
            $w = $self->width;
        }
        elsif ( defined $self->parent->inner_width ) {
            $w = $self->parent->inner_width;
        }
        else {
            $w = $te->{width} / Pango->scale
        }
    }
    
    #
    ## set the layout width now so we can figure out what the height is
    $layout->set_width( $w * Pango->scale );
    
    # now get the extents again to figure out the height
    $te = $layout->get_extents;
    my $h  = defined $self->height ? $self->height : $te->{height} / Pango->scale;
    
    return { width => $w, height => $h };
}

sub size_allocate {
    my ( $self, $cr, $x, $y, $width, $height ) = @_;
    
    #$width  = $self->parent->width  if $self->parent->width;
    #$height = $self->parent->height if $self->parent->height;
   
    # adjust for vertical alignment
    if ( $self->parent->size_allocation ) {
        my $pheight = $self->parent->size_allocation->{height};

        if ( $self->parent->merged_style->vertical_align && $self->parent->merged_style->vertical_align eq 'middle' && $pheight > $height ) {
            my $delta = $pheight - $height;
            $y += $delta / 2 ;
        }
        if ( $self->parent->merged_style->vertical_align && $self->parent->merged_style->vertical_align eq 'bottom' && $pheight > $height ) {
            my $delta = $pheight - $height;
            $y += $delta;
        }
    }
    
    my %allocation = (width => $width, height => $height, x => $x, y => $y);
    my $layout = $self->_layout( $cr );
    $layout->set_width( $width * Pango->scale );
    $self->set_size_allocation( \%allocation );
}

sub _apply_style_to_layout  {
    my ( $self, $additional_atts ) = @_;
    my $layout = $self->_get_layout;
    my $style  = $self->merged_style;
    
    my $attr_list = $style->attr_list;
    
    my $att_iter = $additional_atts->get_iterator;
    while ( defined $att_iter ) {
        my @attributes = $att_iter->get_attrs;
        $attr_list->insert( $_ ) for @attributes;
        
        my $val = $att_iter->next;
        last if ! $val;
    }
    
    $layout->set_attributes( $attr_list );
    $layout->set_alignment( $style->text_align ) if $style->text_align;
}
1;
