<?php

/**
 * SearchModel
 *
 */
class SearchModel
{
    /**
     * @param string searchquery
     * @return array results
     */
    public static function getResults($searchterm)
    {
        //$searchquery = urldecode($searchquery);
        $searchquery = $searchterm.'*';
        $args = array('start' => 0,
                      'howMany' => Config::get('PPP'));

        $args = Helper::filterArgs($args,'search');
        $prefix = Config::get('DB_PREFIX');
        $database = DatabaseFactory::getFactory()->getConnection();

        $userCoordinates = PlaceModel::getPlaceByPostalcode(Session::get('search_plz'));
        if ($userCoordinates)
        {
            $sql = "SELECT SQL_CALC_FOUND_ROWS
                           MATCH(O.title, O.detail, O.tags) AGAINST(:search IN BOOLEAN MODE) AS relevance,
                           IFNULL((Places.lat - ".$userCoordinates->lat.") * (Places.lat - ".$userCoordinates->lat.") +
                           (Places.lon - ".$userCoordinates->lon.") * (Places.lon - ".$userCoordinates->lon."),'x') AS distance,
                           O.id                         AS id,
                           O.type                       AS type,
                           O.title                      AS title,
                           O.detail                     AS detail,
                           O.tags                       AS tags,
                           O.price                      AS price,
                           O.currency                   AS currency,
                           O.unit                       AS unit,
                           O.image                      AS image,
                           O.profile_id                 AS profile_id,
                           O.external                   AS external,
                           O.external_url               AS external_url,
                           O.zipcode                    AS postalcode,
                           O.modified                   AS modified
                    FROM ".$prefix."offers              AS O
                    LEFT JOIN ".$prefix."places         AS Places ON Places.plz = O.zipcode
                    WHERE MATCH(O.title, O.detail, O.tags) AGAINST(:search IN BOOLEAN MODE) AND ".$args['where']."
                    GROUP BY O.id
                    ORDER BY ".$args['order']."
                    LIMIT :start,:limit";
        }
        else
        {
            $sql = "SELECT SQL_CALC_FOUND_ROWS
                           MATCH(title, detail, tags) AGAINST(:search IN BOOLEAN MODE) AS relevance,
                           O.id                         AS id,
                           O.type                       AS type,
                           O.title                      AS title,
                           O.detail                     AS detail,
                           O.tags                       AS tags,
                           O.price                      AS price,
                           O.currency                   AS currency,
                           O.unit                       AS unit,
                           O.image                      AS image,
                           O.profile_id                 AS profile_id,
                           O.external                   AS external,
                           O.external_url               AS external_url,
                           O.modified                   AS modified
                    FROM ".$prefix."offers              AS O
                    WHERE MATCH(O.title, O.detail, O.tags) AGAINST(:search IN BOOLEAN MODE) AND ".$args['where']."
                    ORDER BY ".$args['order']."
                    LIMIT :start,:limit";
        }
        $query = $database->prepare($sql);
        $query->bindParam(':start',     $args['start'],     PDO::PARAM_INT);
        $query->bindParam(':limit',     $args['howMany'],   PDO::PARAM_INT);
        $query->bindParam(':search',    $searchquery,       PDO::PARAM_STR);
        $query->execute();
        $results = array();
        if ($query->rowCount() < 1)
        {
            $results['number'] = 0;
        } else {
            $results['number'] = $database->query("SELECT FOUND_ROWS()")->fetchColumn();
        }

        // save searchterm and number of results for statistics
        if ($searchterm != '')
        {
            self::archiveSearch($searchterm,$results['number']);
        }

        $o = 0; $r = 0;
        $results['offers'] = array();
        $results['requests'] = array();
        foreach ($query->fetchAll() as $offer)
        {
            if (!isset($offer->distance))
            {
                $offer->distance = '[N/A]';
            }
            else
            {
                $offer->distance = PA::getDistance($offer->postalcode);
                if ($offer->distance === false)
                {
                    $offer->distance = '[N/A]';
                }
                elseif ($offer->distance < 3)
                {
                    $offer->distance = 'Umgebung*';
                }
            }

            if ($offer->type == 1)
            {
                $type = 'offers';
                $i = $o;
            } else {
                $type = 'requests';
                $i = $r;
            }

            $results[$type][$i]                 = new stdClass();
            $results[$type][$i]->id             = $offer->id;
            $results[$type][$i]->title          = $offer->title;
            $results[$type][$i]->price          = $offer->price;
            $results[$type][$i]->currency       = $offer->currency;
            $results[$type][$i]->unit           = $offer->unit;
            $results[$type][$i]->image          = $offer->image;
            $results[$type][$i]->profile_id     = $offer->profile_id;
            $results[$type][$i]->external       = $offer->external;
            $results[$type][$i]->external_url   = $offer->external_url;
            $results[$type][$i]->distance       = $offer->distance;
            $results[$type][$i]->modified       = $offer->modified;

            if ($offer->type == 1)
            {
                $o++;
            } else {
                $r++;
            }
        }

        $results['howMany'] = $args['howMany'];
        $results['numberOffers'] = $o;
        $results['numberRequests'] = $r;

        return $results;
    }

    private static function archiveSearch($searchterm, $results)
    {
        $prefix = Config::get('DB_PREFIX');
        $database = DatabaseFactory::getFactory()->getConnection();
        $sql = "INSERT INTO ".$prefix."searches
                    (searchterm, results, created)
                VALUES
                    (:searchterm, :results, NOW())";
        $query = $database->prepare($sql);
        $query->bindParam(':searchterm',    $searchterm,    PDO::PARAM_STR);
        $query->bindParam(':results',       $results,       PDO::PARAM_INT);
        $query->execute();
    }

    public static function clean()
    {
        $qclean = strtolower(Request::post('search',true));

        Session::set('search_plz',
            Request::post('search_zip',true));

        if (Request::post('custom_search',true) == 1) {
            Session::set('search_offers',
                Request::post('search_offers',true) == 1 ? 'y' : 'n');
            Session::set('search_requests',
                Request::post('search_requests',true) == 1 ? 'y' : 'n');
            Session::set('search_internal',
                Request::post('search_intern',true) == 1 ? 'y' : 'n');
            Session::set('search_external',
                Request::post('search_extern',true) == 1 ? 'y' : 'n');
        }

        $qclean = htmlspecialchars($qclean);

        // Remove multiple adjacent spaces
        while (strstr($qclean, "  ")) {
           $qclean = str_replace("  ", " ", $qclean);
        }

        // Replace single spaces with a URL friendly plus sign
        $qclean = str_replace(" ", "+", $qclean);

        // If validation has passed, return search value
        if ($qclean != '') {
           return $qclean;
        }
    }
}
