# This code was forked from the LiveJournal project owned and operated
# by Live Journal, Inc. The code has been modified and expanded by
# Dreamwidth Studios, LLC. These files were originally licensed under
# the terms of the license supplied by Live Journal, Inc, which can
# currently be found at:
#
# http://code.livejournal.org/trac/livejournal/browser/trunk/LICENSE-LiveJournal.txt
#
# In accordance with the original license, this code and all its
# modifications are provided under the GNU General Public License.
# A copy of that license can be found in the LICENSE file included as
# part of this distribution.

package LJ::Directory::Constraint::Location;
use strict;
use warnings;
use base 'LJ::Directory::Constraint';
use Carp qw(croak);
use LJ::Directory::MajorRegion;
use LJ::Directory::SetHandle::MajorRegion;

sub new {
    my ( $pkg, %args ) = @_;
    my $self = bless {}, $pkg;
    $self->{$_} = delete $args{$_} || "" foreach qw(country state city);
    croak "unknown args" if %args;

    return $self;
}

sub country { $_[0]->{country} }
sub state   { $_[0]->{state} }
sub city    { $_[0]->{city} }

sub new_from_formargs {
    my ( $pkg, $args ) = @_;
    my $cn = $args->{loc_cn};
    my $st = $args->{loc_st} || '';
    return undef unless $cn || $st;
    $cn ||= "US";
    $cn = uc $cn;

    my $stateable = exists $LJ::COUNTRIES_WITH_REGIONS{$cn};

    ## Convert full region name to code, if possible
    if ($stateable) {
        my %regions;    ## state code --> state full name
        LJ::load_codes( { $LJ::COUNTRIES_WITH_REGIONS{$cn}->{'type'} => \%regions } );
        my %full_name_to_code = reverse %regions;
        $st = $full_name_to_code{$st} if exists $full_name_to_code{$st};
        $st = uc($st);
    }

    return $pkg->new(
        country => $cn,
        state   => $st,
        city    => $args->{loc_ci}
    );

}

sub cached_sethandle {
    my ($self) = @_;
    my @regids =
        LJ::Directory::MajorRegion->region_ids( $self->country, $self->state, $self->city );
    if (@regids) {
        return LJ::Directory::SetHandle::MajorRegion->new(@regids);
    }

    return undef;
}

sub cache_for { 86400 }

sub matching_uids {
    my $self = shift;
    my $db   = LJ::get_dbh("directory") || LJ::get_db_reader();

    my $p = LJ::get_prop( "user", "sidx_loc" )
        or die "no sidx_loc prop";

    my $country = $self->country || '';
    my $state   = $self->state   || '';
    my $city    = $self->city    || '';

    $country =~ s/[\_\%]//g;    # remove LIKE magic wildcards (underscore and percent)
    $state   =~ s/[\_\%]//g;
    $city    =~ s/[\_\%]//g;

    $state = '%' unless $state;    # unset? any region will ok
    $city  = '%' unless $city;

    my $prefix = join( "-", $country, $state, $city );
    $prefix =~ s/\%-\%$/%/;        # Country-%-%  --> Country-%

    # for efficiency, do a table join here to filter on visible users
    my $uids = $db->selectcol_arrayref(
"SELECT up.userid FROM userprop AS up INNER JOIN user AS u ON up.userid=u.userid WHERE up.upropid=? AND u.statusvis='V' AND up.value LIKE ?",
        undef, $p->{id}, $prefix
    ) || [];
    return @$uids;
}

1;
