package Storm::Role::Query::CanParseUserArgs;

use Storm::SQL::Column;
use Storm::SQL::Literal;
use Storm::SQL::Placeholder;


use Moose::Role;

sub args_to_sql_objects {
    my $self = shift;
    my @args = @_;
    
    # perform substitution on arguments
    my $map = $self->can('_attribute_map') ?  $self->_attribute_map : {};
    for ( @args ) {
        next if ! defined $_;
        
        if ( ! blessed $_) {
            # replace backtick quoted items with ::SQL::Literal object
            if (/^`(.*)`$/) {
                $_ = Storm::SQL::Literal->new( $1 );
            }
            # replace attribute names with column objects
            elsif ( /^\.(\w+)$/) {
                my $attname = $1;
                if ( exists $map->{$1} ) {
                    my $column = Storm::SQL::Column->new(
                        $self->class->meta->storm_table->name . '.' . $map->{$1}->column->name
                    );
                    
                    $_ = $column;
                }
                else {
                    confess qq[bad attribute $1];
                }
            }
            # parse object.attribute notation
            elsif ( $_ =~ /^\.(\w+)\.(\w+)/) {
                if (exists $map->{$1} ) {
                    
                    my $attr = $map->{$1};
                    my $type_constraint = $attr->type_constraint;
                    
                    
                    # we need to account for how maybe types work
                    if ($type_constraint->parent && $type_constraint->parent->name eq 'Maybe') {
                        use Moose::Util::TypeConstraints;
                        $type_constraint = find_type_constraint($type_constraint->{type_parameter});
                        no Moose::Util::TypeConstraints;
                    }
                    
                    my $class;
                    
                    # go through the type heirarchy until we find a Gi::ORM object
                    while ( $type_constraint && ! $class ) {
                        
                        if ($type_constraint->can('class') &&
                            $type_constraint->class &&
                            $type_constraint->class->can('meta') &&
                            $type_constraint->class->meta->does_role('Storm::Role::Object')) {
                    
                            
                            $class = $type_constraint->class;
                            my $meta  = $class->meta;
                            
                            my $child_attr = $meta->get_attribute( $2 );
                            my $column = Storm::SQL::Column->new(
                                $meta->storm_table->name . '.' . $child_attr->column->name
                            );
                            
                            $_ = $column;
                            
                            $self->_from( $class->meta->storm_table );
                            $self->_link(  $attr, $class );
                        }
                        else {
                            $type_constraint = $type_constraint->parent;
                        }
                    }
                }
            }
            # question marks are turned into parameters
            elsif ( $_ eq '?' ) {
                $_ = Storm::SQL::Placeholder->new( value => Storm::SQL::Parameter->new );
            }
            # regular strings are turned into placeholders
            else {
                $_ = Storm::SQL::Placeholder->new( value => $_ );
            }
            
        }
        # if is blessed
        else {
            # if we have a gi-orm object
            # replace the argument with a placeholder
            # containing the identifier
            if ( $_->does( 'Storm::Role::Object' ) ) {                
                $_ = Storm::SQL::Placeholder->new( value => $_->identifier); 
            }
        }
    }
    return @args;
}

no Moose::Role;

1;
