#use warnings;
use strict;

use constant MAX_RECORDS => 24;

################################################################################
sub buildSearchSql {
  my ($params) = @_;
  my $sql = "SELECT i.id As id, i.title As title, concat(substring(i.description, 1, 200), '...') As description, format(i.price, 2) As price, i.deleted As deleted, i.activated As activated, s.id As seller, s.name As seller_name, if(locate('http://', s.website_url), s.website_url, concat('http://', s.website_url)) As website_url FROM item As i LEFT JOIN seller As s ON i.seller = s.id WHERE ";

  if ($params->{criteria}->{deleted}) {
    $sql .= 'i.deleted = 1 ';
  } else {
    $sql .= 'i.deleted != 1 ';

    if (defined $params->{criteria}->{activated}) {
      if ($params->{criteria}->{activated} == 1) {
	$sql .= 'AND i.activated = 1 ';
      } else {
	$sql .= 'AND i.activated = 0 ';
      }
    } else {
      $sql .= 'AND i.activated = 1 ';
    }
  }

  foreach my $kw ( split(/\s+/, $params->{criteria}->{keywords}) ) {
    if ( $params->{criteria}->{title_and_description} ) {
      $sql .= "AND ((i.title like '%$kw%') OR (i.description like '%$kw%')) ";
    } else {
      $sql .= "AND (i.title like '%$kw%') ";
    }
  }

  $sql .= "AND ((i.hbcu = '$params->{criteria}->{hbcu}') OR (i.title like '%$params->{criteria}->{hbcu}%') OR (i.description like '%$params->{criteria}->{hbcu}%')) " if $params->{criteria}->{hbcu};

  if ($params->{criteria}->{category}) {
    $sql .= 'AND (';
    $sql .= "i.categories = $params->{criteria}->{category} ";
    $sql .= "OR i.categories like '%:$params->{criteria}->{category}:%' ";
    $sql .= "OR i.categories like '$params->{criteria}->{category}:%' ";
    $sql .= "OR i.categories like '%:$params->{criteria}->{category}' ";
    $sql .= ") ";
  }

  $sql .= "AND i.price >= $params->{criteria}->{min_price} " if $params->{criteria}->{min_price};
  $sql .= "AND i.price <= $params->{criteria}->{max_price} " if $params->{criteria}->{max_price};
  $sql .= "AND s.name like '%$params->{criteria}->{sellers}%' " if $params->{criteria}->{sellers};
  $sql .= "AND s.id = $params->{criteria}->{seller_id} " if $params->{criteria}->{seller_id};

  $sql .= " ORDER BY $params->{order_by} " if defined $params->{order_by};

  $sql .= "LIMIT $params->{start_record}, $params->{max_records}";

  ###print STDERR "search_sql = $sql\n";

  return $sql;
}

################################################################################
sub getCategories {
  my ($db) = @_;

  return map {
    my @subs = $db->getCategories(WHERE => {parent => $_->{id}},
				  ORDER => 'name');

    for (my $i = 0; $i < scalar(@subs) - 1; $i++) {
      $subs[$i]->{comma} = 1;
    }
    $_->{subcategories} = \@subs;
    $_->{item_count} = $db->getCategoryItemCount($_->{id});
    $_;
  } $db->getCategories(WHERE => {parent => 0}, ORDER => 'name');
}

################################################################################
sub getFeaturedItems {
  my ($db) = @_;
  my @recs = map {
    $_->{picture} = $db->getPicture({item => $_->{id}});
    $_->{price} = sprintf("\$%.2f", $_->{price});
    $_->{hbcu} ||= 'All HBCUs';
    $_;
  } $db->getItems(WHERE => {featured => 1});

  my @records = ();
  for (my $i = 0; $i <= $#recs; $i++) {
    my @array = ();
    push @array, $recs[$i++];

    unless ($i > $#recs) {
      push @array, $recs[$i++];
    }

    unless ($i > $#recs) {
      push @array, $recs[$i++];
    }

    unless ($i > $#recs) {
      push @array, $recs[$i];
    }

    push @records, {columns => \@array};
  }

  return @records;
}

################################################################################
sub getHomepageItems {
  my ($db) = @_;

  return map {
    $_->{picture} = $db->getPicture({item => $_->{id}});
    $_;
  } $db->getItems(WHERE => {featured_homepage => 1}, ORDER => 'hits desc');
}

################################################################################
sub getItem {
  my ($config, $db, $hdb, $id) = @_;
  my $item = $db->getItem({id => $id});

  return unless $item;

  my @cats = map {
    $db->getCategory({id => $_})->{name};
  } split(/:/, $item->{categories});

  $item->{item_id} = $item->{id};
  $item->{categoryNames} = join(', ', @cats);
  $item->{price} = sprintf("\$%.2f", $item->{price});
  $item->{hbcu} ||= 'All HBCUs';
  $item->{hits} ||= 0;
  $item->{seller_name} = getSeller($config, $db, $hdb, 'id', $item->{seller})->{name};
  $item->{"grace_$item->{grace}"} = 1 if defined $item->{grace};
  $item->{"$item->{type}"} = 1 if defined $item->{type};

  my @pictures = $db->getPictures(WHERE => {item => $item->{id}});

  if (@pictures) {
    $item->{pictures} = \@pictures;
    $item->{numPictures} = scalar( @{$item->{pictures}} );
  } else {
    $item->{pictures} = [];
    $item->{numPictures} = 0;
  }

  @{ $item->{reviews} } = map {
    $_->{review_id} = $_->{id};
    $_->{useful} ||= 0;
    $_->{not_useful} ||= 0;
    $_->{registry_data} = $hdb->getRegistryData({registry_id => $_->{registry_id}});
    $_->{registry_name} = $_->{registry_data}->{name};

    for (my $i = 0; $i < $_->{rating}; $i++) {
      push @{$_->{stars}}, {star => $config->{STAR}};
    }
    for (my $i = 0; $i < (5 - $_->{rating}); $i++) {
      push @{$_->{stars}}, {star => $config->{BLANK_STAR}};
    }

    $_;
  } $db->getReviews(WHERE => {item => $item->{id}});

  $item->{totalReviews} = scalar(@{ $item->{reviews} });
  $item->{averageReview} = $db->getItemReviewAverage($item->{id});

  if ($item->{averageReview}) {
    for (my $i = 0; $i < $item->{averageReview}; $i++) {
      push @{$item->{stars}}, {star => $config->{STAR}};
    }
    for (my $i = 0; $i < (5 - $item->{averageReview}); $i++) {
      push @{$item->{stars}}, {star => $config->{BLANK_STAR}};
    }
  }

  return $item;
}

#################################################################################
sub getMyItemsForSale {
  my ($db, $q, $id) = @_;
  my %hash = ();

  $hash{current_page} = $q->param('current_page') || 1;
  $hash{start_record} = ($hash{current_page} - 1) * 25;
  $hash{order_by} = $q->param('order_by');
  $hash{max_records} = 25;

  # Get the items
  my @items = map {
    $_->{num_sold} = $db->getItemPurchaseCount($_->{id});
    $_->{status} = $_->{activated} ? 'Active' : 'Not Active';
    $_->{hits} ||= 0;

    ### Uncomment this when we start to care about item expiration
    ###$_->{status} = 'Expired' if $_->{date_expires} <= $_->{crt_date};

    $_;
  } $db->getSellerItems($id);

  # Handle sorting
  if ($hash{order_by} eq 'hits') {
    @items = sort { $a->{hits} <=> $b->{hits} } @items;
  } elsif ($hash{order_by} eq 'num_sold') {
    @items = sort { $a->{num_sold} cmp $b->{num_sold} } @items;
  } elsif ($hash{order_by} eq 'status') {
    @items = sort { $a->{status} cmp $b->{status} } @items;
  } elsif ($hash{order_by} eq 'title') {
    @items = sort { $a->{title} cmp $b->{title} } @items;
  }

  return prepareSearchResults(\%hash, \@items);
}

#################################################################################
sub getMyPurchasedItems {
  my ($db, $q, $id) = @_;
  my %hash = ();

  $hash{current_page} = $q->param('current_page') || 1;
  $hash{start_record} = ($hash{current_page} - 1) * 25;
  $hash{order_by} = $q->param('order_by');
  $hash{max_records} = 25;

  # Get the items
  print STDERR "user_id = $id\n";
  my @items = map {
    print STDERR "id = $_->{id}\n";
    my $row = $_;
    my $rec = $db->getSeller({id => $row->{seller}});

    $row->{seller_name} = $rec->{name};
    $row->{total} = sprintf("\$%.2f", $row->{total});

    my @t = split /\s/, $row->{date_created};
    $row->{date_created} = $t[0];

    $row;
  } $db->getUserPurchasedItems($id);

  # Handle sorting
  if ($hash{'order_by'} eq 'title') {
    @items = sort { $a->{title} cmp $b->{title} } @items;
  } elsif ($hash{'order_by'} eq 'quantity') {
    @items = sort { $a->{quantity} <=> $b->{quantity} } @items;
  } elsif ($hash{'order_by'} eq 'total') {
    @items = sort { substr($a->{total}, 1) <=> substr($b->{total}, 1) } @items;
  } elsif ($hash{'order_by'} eq 'tstamp') {
    @items = sort { $a->{date_created} cmp $b->{date_created} } @items;
  } elsif ($hash{'order_by'} eq 'seller') {
    @items = sort { $a->{seller_name} cmp $b->{seller_name} } @items;
  }

  return prepareSearchResults(\%hash, \@items);
}

#################################################################################
sub getMySavedItems {
  my ($db, $q, $id) = @_;
  my %hash = ();

  $hash{current_page} = $q->param('current_page') || 1;
  $hash{start_record} = ($hash{current_page} - 1) * 25;
  $hash{order_by} = $q->param('order_by');
  $hash{max_records} = 25;

  # Get the items
  my @items = map {
    my $row = $_;
    my $rec = $db->getSeller({id => $row->{seller}});
    $row->{picture} = $db->getPicture({item => $row->{id}});
    $row->{seller_name} = $rec->{name};
    $row->{price} = sprintf("\$%.2f", $row->{price});

    if ($row->{date}) {
      my @date = split /\s/, $row->{date};
      $row->{date} = $date[0];
    }

    if ((defined $row->{date_expires}) &&
	(defined $row->{crt_date}) &&
	$row->{date_expires} <= $row->{crt_date}) {
      $row->{expired} = 1;
    }

    $row;
  } $db->getUserSavedItems($id);

  # Handle sorting
  if ($hash{'order_by'} eq 'title') {
    @items = sort { $a->{title} cmp $b->{title} } @items;
  } elsif ($hash{'order_by'} eq 'price') {
    @items = sort { substr($a->{price}, 1) <=> substr($b->{price}, 1) } @items;
  } elsif ($hash{'order_by'} eq 'seller') {
    @items = sort { $a->{seller_name} cmp $b->{seller_name} } @items;
  }

  return prepareSearchResults(\%hash, \@items);
}

#################################################################################
sub getMySavedSearches {
  my ($db, $q, $id) = @_;
  my %hash = ();

  $hash{current_page} = $q->param('current_page') || 1;
  $hash{start_record} = ($hash{current_page} - 1) * 25;
  $hash{order_by} = $q->param('order_by');
  $hash{max_records} = 25;

  # Get the items
  my @items = $db->getUserSavedSearches($id);

  # Handle sorting
  if ($hash{'order_by'} eq 'name') {
    @items = sort { $a->{name} cmp $b->{name} } @items;
  }

  return prepareSearchResults(\%hash, \@items);
}

################################################################################
sub getPurchase {
  my ($config, $db, $hdb, $id) = @_;

  my $purchase = $db->getPurchase({id => $id});

  return unless $purchase;

  $purchase->{price} = sprintf("\$%.2f", $purchase->{price});
  $purchase->{total} = sprintf("\$%.2f", $purchase->{total});

  $purchase->{item} = getItem($config, $db, $hdb, $purchase->{item});
  $purchase->{seller} = getSeller($config, $db, $hdb, 'id', $purchase->{seller});
  $purchase->{buyer} = $hdb->getRegistryData({registry_id => $purchase->{buyer}});

  return $purchase;
}

################################################################################
sub getSearchTotalRecordCount {
  my ($db, $sql) = @_;

  $sql =~ s/^.*FROM/SELECT\ COUNT\(\*\)\ FROM/g;
  $sql =~ s/LIMIT.*$//g;

  return $db->execute($sql)->{'COUNT(*)'};
}

################################################################################
sub getSeller {
  my ($config, $db, $hdb, $field, $id) = @_;

  my $seller = $db->getSeller({$field => $id});

  return unless $seller;

  my @cats = map {
    $db->getCategory({id => $_})->{name};
  } split(/:/, $seller->{categories});

  $seller->{seller_id} = $seller->{id};
  $seller->{categoryNames} = join(', ', @cats);
  $seller->{hbcu} ||= 'All HBCUs';
  $seller->{"grace_$seller->{grace}"} = 1;
  $seller->{"$seller->{type}"} = 1;
  $seller->{website_url} = 'http://' . $seller->{website_url}
    unless $seller->{website_url} =~ /^http\:\/\//;

  @{ $seller->{reviews} } = map {
    $_->{useful} ||= 0;
    $_->{not_useful} ||= 0;
    $_->{registry_data} = $hdb->getRegistryData({registry_id => $_->{registry_id}});
    for (my $i = 0; $i < $_->{rating}; $i++) {
      push @{$_->{stars}}, {star => $config->{STAR}};
    }
    for (my $i = 0; $i < (5 - $_->{rating}); $i++) {
      push @{$_->{stars}}, {star => $config->{BLANK_STAR}};
    }

    $_;
  } $db->getReviews(WHERE => {seller => $seller->{id}});

  $seller->{totalReviews} = scalar(@{ $seller->{reviews} });
  $seller->{averageReview} = $db->getSellerReviewAverage($seller->{id});

  my @recs = map {
    $_->{picture} = $db->getPicture({item => $_->{id}});
    $_->{price} = sprintf("\$%.2f", $_->{price});
    $_->{hbcu} ||= 'All HBCUs';
    $_;
  } $db->getSellerPopularItems($seller->{id});

  my @records = ();
  for (my $i = 0; $i <= $#recs; $i++) {
    my @array = ();
    push @array, $recs[$i++];

    unless ($i > $#recs) {
      push @array, $recs[$i++];
    }

    unless ($i > $#recs) {
      push @array, $recs[$i];
    }

    push @records, {columns => \@array};
  }

  $seller->{records} = \@records;
  $seller->{itemCategories} = $db->getSellerItemCategories($seller->{id});

  return $seller;
}

################################################################################
sub prepareSearchResults {
  my ($hash, $items) = @_;

  # Get the total number of records
  $hash->{total_records} = scalar(@$items);

  # Get the start record
  $hash->{start_record} =
    ($hash->{current_page} - 1) * $hash->{max_records} + 1;

  # Reduce to just the records we need
  my $max = ($hash->{max_records} < scalar(@$items)) ?
    $hash->{max_records} : scalar(@$items);
  @$items = splice(@$items, (($hash->{current_page} - 1) * ($hash->{max_records} + 0)), $max);

  # Get the end record
  $hash->{end_record} =
    scalar(@$items) + ($hash->{current_page} - 1) * $hash->{max_records};

  # Get the previous page
  $hash->{previous_page} = $hash->{current_page} - 1
    unless $hash->{current_page} == 1;

  # Get the next page
  $hash->{next_page} = $hash->{current_page} + 1
    if ($hash->{total_records} - $hash->{end_record}) > 0;

  # Set the records
  $hash->{records} = $items;

  return $hash;
}

################################################################################
sub processAccountInfo {
  my ($config, $hdb, $q) = @_;
  my %params = ();

  $params{$_} = $q->param($_) for qw(
				     email
				     password
				     hbcu
				     name
				     phone
				     address
				     city
				     state
				     zip
				    );
  $params{signup_site} = $config->{DOMAIN};
  $params{postdate} = 'now()';

  $hdb->addRegistryData(\%params);

  return $hdb->getRegistryData({email => $params{email}})->{registry_id};
}

################################################################################
sub processContactUs {
  my ($config, $email, $db, $q) = @_;
  my $message = 'Message from ' . $q->param('name') .
    "on the $config->{SITE} Marketplace\n\n" . $q->param('comments');

  $email->sender( $q->param('email') );
  $email->recipients( [{name => "$config->{SITE} Administrator",
			email => "$config->{MARKETPLACE_ADMIN_EMAIL}"}] );

  $email->subject( $q->param('subject') );
  $email->textMessage( $message );

  $email->sendText;
}

################################################################################
sub processItemInformation {
  my ($db, $q) = @_;
  my %params = ();

  $params{$_} = $q->param($_) for qw(
				     hbcu
				     title
				     price
				     shipping_included
				     description
				     more_than_one
				    );
  $params{price} =~ s/\$//g;

  $params{categories} = join(':', $q->param('categories'));
  $params{seller} = $db->getSeller({registry_id => $q->cookie('ID')})->{id};

  if ($q->param('edit')) {
    $db->updateItem(WHERE => {id => $q->param('id')}, PARAMS => \%params);
  } else {
    $params{date_created} = 'now()';
    return $db->addItem(\%params);
  }

  return $q->param('id');
}

################################################################################
sub processItemPaymentReturn {
  my ($db, $q) = @_;
  my %params = ();

  $params{$_} = $q->param($_) for qw(
				     visa
				     paypal
				     mastercard
				     checks
				     amex
				     money_order
				     discover
				     other
				     payment_url
				     instructions
				     accepted
				     grace
				     type
				     policy
				    );

  $db->updateItem(WHERE => {id => $q->param('id')}, PARAMS => \%params);
}

################################################################################
sub processItemPictures {
  my ($fu, $db, $q) = @_;
  my %params = ();

  # Get the binary for the picture
  $params{image} = $fu->getBinary($q->param('image'), $q);
  $params{caption} = $q->param('caption');
  $params{item} = $q->param('id');
  $params{date_created} = 'now()';

  $db->addPicture(\%params);
}

################################################################################
sub processItemReview {
  my ($db, $q) = @_;
  my %params = ();

  $params{$_} = $q->param($_) for qw(
				     item
				     rating
				     title
				     pros
				     cons
				     comments
				    );

  $params{'registry_id'} = $q->cookie('ID');

  $db->addReview(\%params);
}

################################################################################
sub processPurchase {
  my ($db, $q, $item) = @_;
  my %params = ();

  $params{'item'} = $item->{id};
  $params{'title'} = $item->{title};
  $params{'price'} = $item->{price};
  $params{'quantity'} = $q->param('quantity') || 1;
  $params{'total'} = $q->param('total') || $params{'price'};
  $params{'buyer'} = $q->cookie('ID');
  $params{'seller'} = $item->{seller};
  $params{'payment_url'} = $item->{payment_url};
  $params{'price'} =~ s/\$//;
  $params{'total'} =~ s/\$//;

  return $db->addPurchase(\%params);
}

################################################################################
sub processSavedSearch {
  my ($db, $q) = @_;

  my %searchInfo = (activated => 1);
  my $savedSearch = $db->getSavedSearch({id => $q->param('id')});
  my %params = ();

  $searchInfo{page} = $q->param('page') || 1;
  $searchInfo{view} = $q->param('grid_view') || 0;
  $searchInfo{order_by} = $q->param('order_by') || 'asc';

  foreach my $kv (split /\;/, $savedSearch->{params}) {
    my @kv = split /:/, $kv;
    $params{$kv[0]} = $kv[1];
  }

  $searchInfo{criteria} = \%params;

  my $search = search($db, \%searchInfo);

  @{ $search->{records} } = map {
    my $row = $_;
    $row->{picture} = $db->getPicture({item => $row->{id}});
    $row->{num_sold} = $db->getNumItemsSold($row->{id});

    # Handle the status
    if ($row->{deleted}) {
      $row->{status} = 'Deleted';
    } else {
      $row->{status} = $row->{activated} ? 'Activated' : 'Deactivated';
    }

    $row->{hits} ||= 0;
    $row;
  } @{ $search->{records} };

  # Handle any sorting
  $search->{order_by} = $q->param('order_by') || 'price';
  if ($search->{order_by} eq 'title' ||
      $search->{order_by} eq 'status') {
    @{ $search->{records} } = sort { $b->{$search->{order_by}} cmp $a->{$search->{order_by}} } @{ $search->{records} };
  } else {
    @{ $search->{records} } = sort { $b->{$search->{order_by}} <=> $a->{$search->{order_by}} } @{ $search->{records} };
  }

  # Handle the view
  if ($q->param('grid_view')) {
    $search->{view} = 1;

    my @records = ();
    my $numRecords = scalar(@{ $search->{records} }) - 1;
    for (my $i = 0; $i <= $numRecords; $i++) {
      my @array = ();
      push @array, $search->{records}->[$i++];
      unless ($i > $numRecords) {
	push @array, $search->{records}->[$i++];
      }
      unless ($i > $numRecords) {
	push @array, $search->{records}->[$i];
      }
      push @records, {columns => \@array};
    }
    $search->{records} = \@records;
  }

  return $search;
}

################################################################################
sub processSearch {
  my ($db, $q) = @_;
  my %searchInfo;
  my %params;

  $searchInfo{page} = $q->param('page') || 1;
  $searchInfo{max_records} = MAX_RECORDS;

  ### Admin parameters
  if ($q->param('status')) {
    $params{deleted} = 1 if $q->param('status') eq 'deleted';
    if ($q->param('status') eq 'activated') {
      $params{activated} = 1;
    } else {
      $params{activated} = 0;
    }
  }
  ### End Admin parameters

  $params{$_} = $q->param($_) for qw(
				     keywords
				     title_and_description
				     hbcu
				     category
				     min_price
				     max_price
				     sellers
				     seller_id
				    );
  $searchInfo{criteria} = \%params;

  # Save the search if necessary
  if ($q->param('saveSearch')) {
    my %params = ();
    $params{registry_id} = $q->cookie('ID');
    $params{name} = $q->param('search_name');
    $params{params} .= "$_:$searchInfo{criteria}->{$_};" for keys %{$searchInfo{criteria}};
    $db->addSavedSearch(\%params);
  }

  my $search = search($db, \%searchInfo);

  @{ $search->{records} } = map {
    my $row = $_;
    $row->{picture} = $db->getPicture({item => $row->{id}});
    $row->{num_sold} = $db->getNumItemsSold($row->{id});

    # Handle the status
    if ($row->{deleted}) {
      $row->{status} = 'Deleted';
    } else {
      $row->{status} = $row->{activated} ? 'Activated' : 'Deactivated';
    }

    $row->{hits} ||= 0;
    $row;
  } @{ $search->{records} };

  # Handle any sorting
  $search->{order_by} = $q->param('order_by') || 'price';
  if ($search->{order_by} eq 'title' ||
      $search->{order_by} eq 'status') {
    @{ $search->{records} } = sort { $b->{$search->{order_by}} cmp $a->{$search->{order_by}} } @{ $search->{records} };
  } else {
    @{ $search->{records} } = sort { $b->{$search->{order_by}} <=> $a->{$search->{order_by}} } @{ $search->{records} };
  }

  # Handle the view
  if ($q->param('grid_view')) {
    $search->{view} = 1;

    my @records = ();
    my $numRecords = scalar(@{ $search->{records} }) - 1;
    for (my $i = 0; $i <= $numRecords; $i++) {
      my @array = ();
      push @array, $search->{records}->[$i++];
      unless ($i > $numRecords) {
	push @array, $search->{records}->[$i++];
      }
      unless ($i > $numRecords) {
	push @array, $search->{records}->[$i];
      }
      push @records, {columns => \@array};
    }
    $search->{records} = \@records;
  }

  return $search;
}


################################################################################
sub processSeller {
  my ($config, $email, $db, $hdb, $q) = @_;
  my %params = (
		activated => 1,
		store => 1,
	       );

  my $seller = $db->getSeller({registry_id => $q->cookie('ID')});
  my $reg_data = $hdb->getRegistryData({registry_id => $q->cookie('ID')});

  $params{$_} = $reg_data->{$_} for qw(
				       registry_id
				       email
				      );

  $params{$_} = $q->param($_) for qw(
				     name
				     website_url
				     privacy_url
				     description
				     visa
				     paypal
				     mastercard
				     checks
				     amex
				     money_order
				     discover
				     other
				     payment_url
				     instructions
				     accepted
				     grace
				     type
				     policy
				    );

  $params{'categories'} = join(':', $q->param('categories'));

  if ($seller) {
    $db->updateSeller(WHERE => {id => $seller->{id}}, PARAMS => \%params);
  } else {
    $params{date_created} = 'now()';

    $db->addSeller(\%params);

    $seller = $db->getSeller({registry_id => $q->cookie('ID')});

    # Send email to staff
    sendNewMerchantEmail($config, $email, $seller);
  }
}

################################################################################
sub processSendEmail {
  my ($config, $email, $db, $hdb, $q) = @_;
  my $item = &getItem($config, $db, $hdb, $q->param('id'));
  my $reg_data = $hdb->getRegistryData({registry_id => $q->cookie('ID')});
  my $comments = $q->param('comments');

  $email->addRecipient({email => $q->param('receiver')});
  $email->sender($config->{ADMIN_EMAIL});
  $email->subject($q->param('subject'));

  my $message = qq~
You have been invited by $reg_data->{name} to check out this item at the $config->{SITE} Marketplace:

     $item->{title}

To view this item, goto the following link:

     $config->{MARKETPLACE_VIEW_ITEM}?id=$item->{id}

$reg_data->{name} writes:
$comments


===================================================
Your Friends,

$config->{SITE} Marketplace
~;

  $email->textMessage($message);

  $email->sendText;
}

################################################################################
sub search {
  my ($db, $params) = @_;
  my ($sql, $records);
  my %search;

  # 1.) Build the sql
  my %vars = (criteria => $params->{criteria},
	      start_record => (($params->{page} - 1) * $params->{max_records}),
	      max_records => $params->{max_records},
	      order_by => $params->{order_by});
  $sql = buildSearchSql(\%vars);

  ###print STDERR "search_sql = $sql\n";

  # 2.) Perform the search
  $search{sql} = $sql;
  my @records = $db->execute($sql);
  $search{records} = \@records;
  $search{total_records} = getSearchTotalRecordCount($db, $sql);

  # 3.) Prepare return data
  $search{$_} = $params->{$_} for qw(
				     page
				     max_records
				     order_by
				    );

  push @{$search{criteria}}, {name => $_, value => $params->{criteria}->{$_}}
    for keys %{$params->{criteria}};

  $search{start_record} = (($search{page} - 1) * $search{max_records}) + 1;
  $search{end_record} =
    scalar(@{ $search{records} }) + (($search{page} - 1) * $search{max_records});
  $search{previous_page} = $search{page} - 1 if $search{page} != 1;
  $search{next_page} = $search{page} + 1
    if ($search{total_records} - $search{end_record}) > 0;

  return \%search;
}

################################################################################
sub sendNewMerchantEmail {
  my ($config, $email, $seller) = @_;

  $email->addRecipient({name => $config->{SITE},
			email => $config->{MARKETPLACE_ADMIN_EMAIL}});
  $email->sender($config->{MARKETPLACE_ADMIN_EMAIL});
  $email->subject("$config->{SITE} Marketplace Store Registration");
  $email->textMessage(qq(
The following merchant has completed registration on the $config->{SITE} Marketplace.

Name: $seller->{name}
Email: $seller->{email}

));

  $email->sendText;
}

################################################################################
sub sendPurchaseEmail {
  my ($config, $db, $hdb, $email, $id) = @_;
  my $purchase = getPurchase($config, $db, $hdb, $id);

  $email->addRecipient({name => $purchase->{seller}->{name},
			email => $purchase->{seller}->{email}});
  $email->addRecipient({name => $config->{SITE},
			email => $config->{MARKETPLACE_ADMIN_EMAIL}});
  $email->sender($config->{MARKETPLACE_ADMIN_EMAIL});
  $email->subject("$config->{SITE} Marketplace Purchase Notification (Item #: $purchase->{item}->{id}, Title: $purchase->{title})");
  $email->textMessage(qq(
Dear $purchase->{seller}->{name},

A purchase was recorded on the $config->{SITE} Marketplace for one of your items.
Please contact the buyer to handle the transaction. The information below
describes the purchase.

Item #: $purchase->{item}->{id}
Title: $purchase->{title}
Price: $purchase->{price}
Quantity: $purchase->{quantity}
Total: $purchase->{total}
Buyer: $purchase->{buyer}->{name}
Buyer Email: $purchase->{buyer}->{email}
Time of Purchase: $purchase->{date_created}


Thank You for using the $config->{SITE} Marketplace.

$config->{SITE}

));

  $email->sendText;
}

1;
