package User::Address;

use strict;

#use warnings;
use Carp;

use lib '/app/tools/common/lib';

#use Common::TiedCode;
use Common::RSDB;

use constant DB_TABLE => "address";

my @attributes = qw(address_id
  user_id
  address_type_id
  address1
  address2
  city
  state
  postal_code
  country
  province
  date_created
  date_modified
);

my @xml_attributes = qw(AddressID
  UserID
  AddressTypeID
  Address1
  Address2
  City
  State
  PostalCode
  Country
  Province
  DateCreated
  DateModified
);

use lib '/app/tools/data_classes/lib';
use Item;
use base 'Item';

# --------------------------------
# Constructor
# --------------------------------
sub new {
    my $class = shift;
    my %args  = @_;

    my $self = $class->SUPER::new(@_);

    # we want the global db, so this will
    # override what the base class set up.
    $self->{dbo} = new Common::RSDB( client_id => 0 );
    $self->_init(%args);

    return $self;
}

sub _init {
    my $self = shift;
    my %args = @_;

    # initialize user properties
    foreach (@attributes) {
        $self->{$_} = undef;
    }

    $self->{errstr} = undef;
    $self->{dirty}  = 0;

    # are we creating an existing Address?
    if ( $args{address_id} ) {
        $self->Load( address_id => $args{address_id} );
    }

    return $self;
}

# --------------------------------
# Properties
# --------------------------------

# cannot set
sub AddressID {
    my $self = shift;
    $self->{address_id};
}

sub UserID {
    my $self = shift;
    if (@_) {
        my ($new_val) = @_;
        if ( $new_val ne $self->{user_id} ) {
            $self->{user_id} = $new_val;
            $self->{dirty}   = 1;
        }
    } else {
        return $self->{user_id};
    }
}

sub AddressTypeID {
    my $self = shift;
    if (@_) {
        my ($new_val) = @_;
        if ( $new_val ne $self->{address_type_id} ) {
            $self->{address_type_id} = $new_val;
            $self->{dirty}           = 1;
        }
    } else {
        return $self->{address_type_id};
    }
}

sub Address1 {
    my $self = shift;
    if (@_) {
        my ($new_val) = @_;
        if ( $new_val ne $self->{address1} ) {
            $self->{address1} = $new_val;
            $self->{dirty}    = 1;
        }
    } else {
        return $self->{address1};
    }
}

sub Address2 {
    my $self = shift;
    if (@_) {
        my ($new_val) = @_;
        if ( $new_val ne $self->{address2} ) {
            $self->{address2} = $new_val;
            $self->{dirty}    = 1;
        }
    } else {
        return $self->{address2};
    }
}

sub City {
    my $self = shift;
    if (@_) {
        my ($new_val) = @_;
        if ( $new_val ne $self->{city} ) {
            $self->{city}  = $new_val;
            $self->{dirty} = 1;
        }
    } else {
        return $self->{city};
    }
}

sub State {
    my $self = shift;
    if (@_) {
        my ($new_val) = @_;
        if ( $new_val ne $self->{state} ) {
            $self->{state} = $new_val;
            $self->{dirty} = 1;
        }
    } else {
        return $self->{state};
    }
}

sub Country {
    my $self = shift;
    if (@_) {
        my ($new_val) = @_;
        if ( $new_val ne $self->{country} ) {
            $self->{country} = $new_val;
            $self->{dirty}   = 1;
        }
    } else {
        return $self->{country};
    }
}

sub PostalCode {
    my $self = shift;
    if (@_) {
        my ($new_val) = @_;
        if ( $new_val ne $self->{postal_code} ) {
            $self->{postal_code} = $new_val;
            $self->{dirty}       = 1;
        }
    } else {
        return $self->{postal_code};
    }
}

sub Province {
    my $self = shift;
    if (@_) {
        my ($new_val) = @_;
        if ( $new_val ne $self->{province} ) {
            $self->{province} = $new_val;
            $self->{dirty}    = 1;
        }
    } else {
        return $self->{province};
    }
}

# cannot set
sub DateCreated {
    my $self = shift;
    return $self->{date_created};
}

# cannot set
sub DateModified {
    my $self = shift;
    return $self->{date_modified};
}

# cannot set
sub Error {
    my $self = shift;
    return $self->{errstr};
}

# -------------------------------
# Public Methods
# -------------------------------
sub Load {
    my $self = shift;
    my %args = @_;

    my $sql;
    if ( $args{address_id} =~ /^\d+$/ ) {
        $sql = "select * from " . DB_TABLE . " where address_id=" . $self->{dbo}->DBQuote( $args{address_id} );
    } else {
        $self->{errstr} = "address_id ($args{address_id}) not specified or not valid";
        return undef;
    }

    my $sth = $self->{dbo}->DoCmd($sql);
    if ( !defined $sth ) {
        $self->{errstr} = "database error: " . $DBI::errstr;
        return undef;
    }

    my $href = $sth->fetchrow_hashref();
    if ( !defined $href ) {
        $self->{errstr} = "no address record for address_id ($args{address_id})";
        return undef;
    }

    $self->_load($href);

    return 1;
}

sub Save {
    my $self = shift;

    return if ( !$self->{dirty} );

    # create sql for saving the user object
    my @set_fields;
    foreach my $attrib (@attributes) {

        # attributes to skip
        next if (/^(date_created|date_modified|address_id)$/);
        my $new_val = $self->{$attrib};
        next if ( !defined $new_val );

        if ( $self->{$attrib} !~ /^null$/i ) {
            $new_val = $self->{dbo}->DBQuote($new_val);
        }
        push @set_fields, $attrib . "=" . $new_val;
    }

    return undef if ( !@set_fields );

    # update or insert?
    if ( defined $self->{address_id} && $self->{address_id} =~ /^\d+$/ ) {
        my $sql = "UPDATE " . DB_TABLE . " SET " . join( ', ', @set_fields ) . " WHERE address_id=" . $self->{address_id};
        $self->{dbo}->DoCmd($sql);
    } else {
        my $sql = "INSERT INTO " . DB_TABLE . " SET date_created=now(), " . join( ', ', @set_fields );
        $self->{dbo}->DoCmd($sql);
        $self->{address_id} = $self->{dbo}->LastInsertID;
    }

    # NOTE: At this point, we *should* re-load our user object from the database to get the
    # correct values for date_modified (inserts and updates) and date_created (inserts only).
    # But for now, until we realize a need for those values after a Save, we will avoid another
    # database hit and skip grabbing the latest data. If it is decided those values are needed,
    # uncomment the following line:

    # $self->Load(address_id => $self->AddressID);

    $self->{dirty} = 0;

    return 1;
}

sub GetObjectXML {
    my $self = shift;

    return $self->SUPER::GetObjectXML(@xml_attributes);
}

# -------------------------------
# Private Methods
# -------------------------------
sub _load {
    my $self = shift;
    my $href = shift;

    map { $self->{$_} = $href->{$_} } @attributes;
}

%User::Address::COUNTRIES = (
    US => 'UNITED STATES',
    AF => 'AFGHANISTAN',
    AX => 'ALAND ISLANDS',
    AL => 'ALBANIA',
    DZ => 'ALGERIA',
    AS => 'AMERICAN SAMOA',
    AD => 'ANDORRA',
    AO => 'ANGOLA',
    AI => 'ANGUILLA',
    AQ => 'ANTARCTICA',
    AG => 'ANTIGUA AND BARBUDA',
    AR => 'ARGENTINA',
    AM => 'ARMENIA',
    AW => 'ARUBA',
    AU => 'AUSTRALIA',
    AT => 'AUSTRIA',
    AZ => 'AZERBAIJAN',
    BS => 'BAHAMAS',
    BH => 'BAHRAIN',
    BD => 'BANGLADESH',
    BB => 'BARBADOS',
    BY => 'BELARUS',
    BE => 'BELGIUM',
    BZ => 'BELIZE',
    BJ => 'BENIN',
    BM => 'BERMUDA',
    BT => 'BHUTAN',
    BO => 'BOLIVIA',
    BA => 'BOSNIA AND HERZEGOVINA',
    BW => 'BOTSWANA',
    BV => 'BOUVET ISLAND',
    BR => 'BRAZIL',

    # IO  => 'BRITISH INDIAN OCEAN TERRITORY',
    BN => 'BRUNEI DARUSSALAM',
    BG => 'BULGARIA',
    BF => 'BURKINA FASO',
    BI => 'BURUNDI',
    KH => 'CAMBODIA',
    CM => 'CAMEROON',
    CA => 'CANADA',
    CV => 'CAPE VERDE',
    KY => 'CAYMAN ISLANDS',
    CF => 'CENTRAL AFRICAN REPUBLIC',
    TD => 'CHAD',
    CL => 'CHILE',
    CN => 'CHINA',
    CX => 'CHRISTMAS ISLAND',

    # CC  => 'COCOS (KEELING) ISLANDS',
    CO => 'COLOMBIA',
    KM => 'COMOROS',
    CG => 'CONGO',

    # CD  => 'CONGO, THE DEMOCRATIC REPUBLIC OF THE',
    CK => 'COOK ISLANDS',
    CR => 'COSTA RICA',
    CI => 'CÔTE D\'IVOIRE',
    HR => 'CROATIA',
    CU => 'CUBA',
    CY => 'CYPRUS',
    CZ => 'CZECH REPUBLIC',
    DK => 'DENMARK',
    DJ => 'DJIBOUTI',
    DM => 'DOMINICA',
    DO => 'DOMINICAN REPUBLIC',
    EC => 'ECUADOR',
    EG => 'EGYPT',
    SV => 'EL SALVADOR',
    GQ => 'EQUATORIAL GUINEA',
    ER => 'ERITREA',
    EE => 'ESTONIA',
    ET => 'ETHIOPIA',

    # FK  => 'FALKLAND ISLANDS (MALVINAS)',
    FO => 'FAROE ISLANDS',
    FJ => 'FIJI',
    FI => 'FINLAND',
    FR => 'FRANCE',
    GF => 'FRENCH GUIANA',
    PF => 'FRENCH POLYNESIA',

    # TF  => 'FRENCH SOUTHERN TERRITORIES',
    GA => 'GABON',
    GM => 'GAMBIA',
    GE => 'GEORGIA',
    DE => 'GERMANY',
    GH => 'GHANA',
    GI => 'GIBRALTAR',
    GR => 'GREECE',
    GL => 'GREENLAND',
    GD => 'GRENADA',
    GP => 'GUADELOUPE',
    GU => 'GUAM',
    GT => 'GUATEMALA',
    GN => 'GUINEA',
    GW => 'GUINEA-BISSAU',
    GY => 'GUYANA',
    HT => 'HAITI',

    # HM  => 'HEARD ISLAND AND MCDONALD ISLANDS',
    HN => 'HONDURAS',
    HK => 'HONG KONG',
    HU => 'HUNGARY',
    IS => 'ICELAND',
    IN => 'INDIA',
    ID => 'INDONESIA',
    IR => 'IRAN',
    IQ => 'IRAQ',
    IE => 'IRELAND',
    IL => 'ISRAEL',
    IT => 'ITALY',
    JM => 'JAMAICA',
    JP => 'JAPAN',
    JO => 'JORDAN',
    KZ => 'KAZAKHSTAN',
    KE => 'KENYA',
    KI => 'KIRIBATI',
    KP => 'KOREA',
    KR => 'KOREA, REPUBLIC OF',
    KW => 'KUWAIT',
    KG => 'KYRGYZSTAN',

    # LA  => 'LAO PEOPLE\'S DEMOCRATIC REPUBLIC',
    LV => 'LATVIA',
    LB => 'LEBANON',
    LS => 'LESOTHO',
    LR => 'LIBERIA',
    LY => 'LIBYA',
    LI => 'LIECHTENSTEIN',
    LT => 'LITHUANIA',
    LU => 'LUXEMBOURG',
    MO => 'MACAO',

    # MK  => 'MACEDONIA, THE FORMER YUGOSLAV REPUBLIC OF',
    MG => 'MADAGASCAR',
    MW => 'MALAWI',
    MY => 'MALAYSIA',
    MV => 'MALDIVES',
    ML => 'MALI',
    MT => 'MALTA',
    MH => 'MARSHALL ISLANDS',
    MQ => 'MARTINIQUE',
    MR => 'MAURITANIA',
    MU => 'MAURITIUS',
    YT => 'MAYOTTE',
    MX => 'MEXICO',

    # FM  => 'MICRONESIA, FEDERATED STATES OF',
    MD   => 'MOLDOVA, REPUBLIC OF',
    MC   => 'MONACO',
    MN   => 'MONGOLIA',
    MS   => 'MONTSERRAT',
    MA   => 'MOROCCO',
    MZ   => 'MOZAMBIQUE',
    MM   => 'MYANMAR',
    NA   => 'NAMIBIA',
    NR   => 'NAURU',
    NP   => 'NEPAL',
    NL   => 'NETHERLANDS',
    AN   => 'NETHERLANDS ANTILLES',
    NC   => 'NEW CALEDONIA',
    NZ   => 'NEW ZEALAND',
    NI   => 'NICARAGUA',
    'NE' => 'NIGER',
    NG   => 'NIGERIA',
    NU   => 'NIUE',
    NF   => 'NORFOLK ISLAND',

    # MP  => 'NORTHERN MARIANA ISLANDS',
    NO => 'NORWAY',
    OM => 'OMAN',
    PK => 'PAKISTAN',
    PW => 'PALAU',

    # PS  => 'PALESTINIAN TERRITORY, OCCUPIED',
    PA => 'PANAMA',
    PG => 'PAPUA NEW GUINEA',
    PY => 'PARAGUAY',
    PE => 'PERU',
    PH => 'PHILIPPINES',
    PN => 'PITCAIRN',
    PL => 'POLAND',
    PT => 'PORTUGAL',
    PR => 'PUERTO RICO',
    QA => 'QATAR',
    RE => 'RÉUNION',
    RO => 'ROMANIA',
    RU => 'RUSSIAN FEDERATION',
    RW => 'RWANDA',
    SH => 'SAINT HELENA',
    KN => 'SAINT KITTS AND NEVIS',
    LC => 'SAINT LUCIA',

    # PM  => 'SAINT PIERRE AND MIQUELON',
    # VC  => 'SAINT VINCENT AND THE GRENADINES',
    WS => 'SAMOA',
    SM => 'SAN MARINO',
    ST => 'SAO TOME AND PRINCIPE',
    SA => 'SAUDI ARABIA',
    SN => 'SENEGAL',
    CS => 'SERBIA AND MONTENEGRO',
    SC => 'SEYCHELLES',
    SL => 'SIERRA LEONE',
    SG => 'SINGAPORE',
    SK => 'SLOVAKIA',
    SI => 'SLOVENIA',
    SB => 'SOLOMON ISLANDS',
    SO => 'SOMALIA',
    ZA => 'SOUTH AFRICA',

    # GS  => 'SOUTH GEORGIA AND THE SOUTH SANDWICH ISLANDS',
    ES => 'SPAIN',
    LK => 'SRI LANKA',
    SD => 'SUDAN',
    SR => 'SURINAME',

    # SJ  => 'SVALBARD AND JAN MAYEN',
    SZ => 'SWAZILAND',
    SE => 'SWEDEN',
    CH => 'SWITZERLAND',
    SY => 'SYRIAN ARAB REPUBLIC',
    TW => 'TAIWAN',
    TJ => 'TAJIKISTAN',
    TZ => 'TANZANIA',
    TH => 'THAILAND',
    TL => 'TIMOR-LESTE',
    TG => 'TOGO',
    TK => 'TOKELAU',
    TO => 'TONGA',
    TT => 'TRINIDAD AND TOBAGO',
    TN => 'TUNISIA',
    TR => 'TURKEY',
    TM => 'TURKMENISTAN',

    # TC  => 'TURKS AND CAICOS ISLANDS',
    TV => 'TUVALU',
    UG => 'UGANDA',
    UA => 'UKRAINE',
    AE => 'UNITED ARAB EMIRATES',
    GB => 'UNITED KINGDOM',

    # UM  => 'UNITED STATES MINOR OUTLYING ISLANDS',
    UY => 'URUGUAY',
    UZ => 'UZBEKISTAN',
    VU => 'VANUATU',
    VA => 'VATICAN CITY STATE',
    VE => 'VENEZUELA',
    VN => 'VIET NAM',
    VG => 'VIRGIN ISLANDS, BRITISH',
    VI => 'VIRGIN ISLANDS, U.S.',

    # WF  => 'WALLIS AND FUTUNA',
    # EH  => 'WESTERN SAHARA',
    YE => 'YEMEN',
    ZM => 'ZAMBIA',
    ZW => 'ZIMBABWE',
);

%User::Address::US_STATES = (
    AL   => 'Alabama',
    AK   => 'Alaska',
    AZ   => 'Arizona',
    AR   => 'Arkansas',
    CA   => 'California',
    CO   => 'Colorado',
    CT   => 'Connecticut',
    DE   => 'Delaware',
    DC   => 'District of Columbia',
    FL   => 'Florida',
    GA   => 'Georgia',
    HI   => 'Hawaii',
    ID   => 'Idaho',
    IL   => 'Illinois',
    IN   => 'Indiana',
    IA   => 'Iowa',
    KS   => 'Kansas',
    KY   => 'Kentucky',
    LA   => 'Louisiana',
    ME   => 'Maine',
    MD   => 'Maryland',
    MA   => 'Massachusetts',
    MI   => 'Michigan',
    MN   => 'Minnesota',
    MS   => 'Mississippi',
    MO   => 'Missouri',
    MT   => 'Montana',
    'NE' => 'Nebraska',
    NV   => 'Nevada',
    NH   => 'New Hampshire',
    NJ   => 'New Jersey',
    NM   => 'New Mexico',
    NY   => 'New York',
    NC   => 'North Carolina',
    ND   => 'North Dakota',
    OH   => 'Ohio',
    OK   => 'Oklahoma',
    OR   => 'Oregon',
    PA   => 'Pennsylvania',
    RI   => 'Rhode Island',
    SC   => 'South Carolina',
    SD   => 'South Dakota',
    TN   => 'Tennessee',
    TX   => 'Texas',
    UT   => 'Utah',
    VT   => 'Vermont',
    VA   => 'Virginia',
    WA   => 'Washington',
    WV   => 'West Virginia',
    WI   => 'Wisconsin',
    WY   => 'Wyoming',

    # AS   => 'American Samoa',
    # FM   => 'Federated States of Micronesia',
    # GU   => 'Guam',
    # MH   => 'Marshall Islands',
    # MP   => 'Northern Mariana Islands',
    # PW   => 'Palau',
    # VI   => 'Virgin Islands',
    # PR   => 'Puerto Rico',

    # AA   => 'Armed Forces (AA)',
    # AE   => 'Armed Forces (AE)',
    # AP   => 'Armed Forces (AP)',
);

1;
#
#
# ---------------------------------------------
# End package User::Address
# ---------------------------------------------

# ---------------------------------------------
# Start package User::Addresses
# ---------------------------------------------
#
#
package User::Addresses;

use constant DB_TABLE => "address";

use lib '/app/tools/data_classes/lib';
use Items;
use base 'Items';

# --------------------------------
# Constructor
# --------------------------------
sub new {
    my $class = shift;
    my %args  = @_;

    my $self = $class->SUPER::new(@_);

    # $self->_init(%args);

    return $self;
}

sub _init {
    my $self = shift;
    my %args = @_;
}

sub GetByUser {
    my $self    = shift;
    my %args    = @_;
    my $user_id = $args{user_id} || return undef;

    my $sql = "SELECT * FROM " . DB_TABLE . " WHERE user_id=$user_id";

    return $self->getByQuery($sql);
}

###
1;    # Play nicely.
###
