<?php
/*******************************************************************************

    Copyright 2014 Whole Foods Co-op

    This file is part of CORE-POS.

    IT CORE is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    IT CORE is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    in the file license.txt along with IT CORE; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

*********************************************************************************/

namespace COREPOS\Fannie\API\webservices; 
use COREPOS\Fannie\API\data\DataCache;
use COREPOS\Fannie\API\member\MemberREST;
use COREPOS\Fannie\API\item\ItemText;
use \FannieDB;
use \FannieConfig;

class FannieAutoComplete extends FannieWebService 
{
    
    public $type = 'json'; // json/plain by default

    /**
      Do whatever the service is supposed to do.
      Should override this.
      @param $args array of data
      @return an array of data
    */
    public function run($args=array())
    {
        $ret = array();
        if (!property_exists($args, 'field') || !property_exists($args, 'search')) {
            // missing required arguments
            $ret['error'] = array(
                'code' => -32602,
                'message' => 'Invalid parameters',
            );
            return $ret;
        } else if (strlen($args->search) < 1) {
            // search term is too short
            $ret['error'] = array(
                'code' => -32602,
                'message' => 'Invalid parameters',
            );
            return $ret;
        }

        $dbc = FannieDB::getReadOnly(FannieConfig::factory()->get('OP_DB'));
        switch (strtolower($args->field)) {
            case 'item':
                $res = false;
                if (!is_numeric($args->search)) {
                    $term = '%' . $args->search . '%';
                    $queryArgs = array($term, $term, $term, $term);
                    $also = "";
                    if (property_exists($args, 'superID')) {
                        $also = " AND m.superID=? ";
                        $queryArgs[] = $args->superID;
                    }
                    $prep = $dbc->prepare('SELECT p.upc,
                                            p.description AS posDesc,
                                            MAX(p.size) AS size,
                                            ' . ItemText::longBrandSQL() . ',
                                            ' . ItemText::longDescriptionSQL() . ',
                                            MAX(l.likeCode) AS likeCode,
                                            MAX(p.scale) AS scale
                                           FROM products AS p
                                            LEFT JOIN productUser AS u ON u.upc=p.upc
                                            LEFT JOIN MasterSuperDepts AS m ON p.department=m.dept_ID
                                            LEFT JOIN upcLike AS l ON p.upc=l.upc
                                           WHERE (p.description LIKE ?
                                            OR p.brand LIKE ?
                                            OR u.description LIKE ?
                                            OR u.brand LIKE ?)
                                            ' . $also . '
                                            AND p.inUse=1
                                           GROUP BY p.upc,
                                            p.brand,
                                            u.brand,
                                            p.description,
                                            u.description
                                           ORDER BY MAX(p.last_sold) DESC, p.description');
                    $res = $dbc->execute($prep, $queryArgs);
                } elseif (ltrim($args->search, '0') != '') {
                    $prep = $dbc->prepare('
                        SELECT p.upc,
                            p.upc AS description,
                            p.upc AS posDesc,
                            \'\' AS brand,
                            \'\' AS size,
                            \'\' AS likeCode,
                            MAX(p.scale) AS scale
                        FROM products AS p
                        WHERE p.upc LIKE ?
                        GROUP BY p.upc');
                    $res = $dbc->execute($prep, array('%'.$args->search . '%'));
                }
                $wide = (isset($args->wide) && $args->wide) ? true : false;
                $lc = (isset($args->lc) && $args->lc) ? true : false;
                while ($res && $row = $dbc->fetch_row($res)) {
                    $bigLabel = (!empty($row['brand']) ? $row['brand'] . ' ' : '') . $row['description'];
                    if ($row['size']) {
                        $bigLabel .= ' (' . $row['size'] . ')';
                    }
                    if ($lc && $row['likeCode']) {
                        $bigLabel .= ' LC' . $row['likeCode'];
                        $row['posDesc'] = ' LC' . $row['likeCode'] . ' ' . $row['posDesc'];
                    } elseif ($lc) {
                        continue;
                    }
                    if ($lc) {
                        $row['posDesc'] .= ' ' . ($row['scale'] ? '(lb)' : '(ea)');
                    }
                    $ret[] = array(
                        'label' => $wide ? $bigLabel : $row['posDesc'],
                        'value' => $row['upc'],
                    );
                }

                return $ret;

            case 'brand':
                $prep = $dbc->prepare('SELECT brand
                                       FROM products
                                       WHERE brand LIKE ?
                                       GROUP BY brand
                                       ORDER BY brand');
                $res = $dbc->execute($prep, array($args->search . '%'));
                while ($row = $dbc->fetch_row($res)) {
                    $ret[] = $row['brand'];
                }

                return $ret;

            case 'long_brand':
                $prep = $dbc->prepare('
                    SELECT u.brand
                    FROM productUser AS u
                        ' . \DTrans::joinProducts('u', 'p', 'INNER') . '
                    WHERE u.brand LIKE ?
                    GROUP BY u.brand
                    ORDER BY u.brand');
                $res = $dbc->execute($prep, array($args->search . '%'));
                while ($row = $dbc->fetch_row($res)) {
                    $ret[] = $row['brand'];
                }

                return $ret;

            case 'vendor':
                $prep = $dbc->prepare('SELECT vendorID,
                                        vendorName
                                       FROM vendors
                                       WHERE vendorName LIKE ?
                                       ORDER BY vendorName');
                $res = $dbc->execute($prep, array($args->search . '%'));
                while ($row = $dbc->fetch_row($res)) {
                    $ret[] = $row['vendorName'];
                }

                return $ret;

            case 'catalog':
                list($vID,$search) = explode(':', $args->search);
                $prep = $dbc->prepare('SELECT sku, description, cost, size, units
                                       FROM vendorItems
                                       WHERE vendorID=?
                                        AND vendorDept > 1
                                        AND (sku LIKE ? OR description LIKE ?)
                                       ORDER BY description');
                $search = '%' . $search . '%';
                $res = $dbc->execute($prep, array($vID, $search, $search));
                while ($row = $dbc->fetch_row($res)) {
                    $str = "{$row['sku']} {$row['description']} {$row['size']}/{$row['units']} \${$row['cost']}";
                    $ret[] = array(
                        'label' => $str,
                        'value' => $str,
                    );
                }
                return $ret;

            case 'mfirstname':
            case 'mlastname':
            case 'maddress':
            case 'mcity':
            case 'memail':
                return MemberREST::autoComplete($args->field, $args->search);

            case 'mfirstnamen':
            case 'mlastnamen':
            case 'maddressn':
            case 'mcityn':
            case 'memailn':
                return MemberREST::autoComplete(substr($args->field, 0, strlen($args->field)-1), $args->search, true);

            case 'sku':
                $query = 'SELECT sku
                          FROM vendorItems
                          WHERE sku LIKE ? ';
                $param = array($args->search . '%');
                if (property_exists($args, 'vendor_id')) {
                    $query .= ' AND vendorID=? ';
                    $param[] = $args->vendor_id;
                }
                $query .= 'GROUP BY sku
                          ORDER BY sku';
                $prep = $dbc->prepare($query);
                $res = $dbc->execute($prep, $param);
                while ($row = $dbc->fetch_row($res)) {
                    $ret[] = $row['sku'];
                    if (count($ret) > 50) {
                        break;
                    }
                }
            
                return $ret;

            case 'unit':
                $query = '
                    SELECT unitofmeasure
                    FROM products
                    WHERE unitofmeasure LIKE ?
                    GROUP BY unitofmeasure
                    ORDER BY unitofmeasure';
                $param = array($args->search . '%');
                $prep = $dbc->prepare($query);
                $res = $dbc->execute($prep, $param);
                while ($row = $dbc->fetchRow($res)) {
                    $ret[] = $row['unitofmeasure'];
                    if (count($ret) > 50) {
                        break;
                    }
                }

                return $ret;

            case 'page':
                $pages = DataCache::getFile('forever', 'pageAutoComplete');
                if ($pages === false) {
                    return $ret;
                }
                $pages = unserialize($pages);
                if (!is_array($pages) || !isset($pages['ttl']) || time() > $pages['ttl']) {
                    $all = array();
                    $acceptsNumbers = array();
                    $url = FannieConfig::config('URL');
                    $root = FannieConfig::config('ROOT');
                    foreach (\FannieAPI::listModules('FanniePage') as $obj) {
                        if (!$obj->discoverable) {
                            continue;
                        }
                        $refl = new \ReflectionClass($obj);
                        $link = $url . str_replace($root, '', $reflect->getFileName());
                        $all[$obj->description] = $link;
                        if (isset($obj->accepts['numbers'])) {
                            $acceptsNumbers[$obj->description] = $link . '?' . urlencode($obj->accepts['numbers']);
                        }
                    }
                    $pages = array(
                        'all' => $all,
                        'numbers' => $acceptsNumbers,
                        'ttl' => time() + (24*60*60),
                    );
                    DataCache::putFile('forever', serialize($pages), 'pageAutoComplete');
                }
                if (!is_numeric($this->search)) {
                    $lower = strtolower($this->search);
                    foreach ($pages['all'] as $description => $link) {
                        if (strpos(strtolower($description), $lower) !== false) {
                            $ret[] = array('label' => $description, 'value'=>$link);
                        }
                    }
                } else {
                    foreach ($pages['numbers'] as $description => $link) {
                        $ret[] = array('label' => $description, 'value' => $link . '=' . $this->search);
                    }
                }
                return $ret;

            case 'ewic':
                $query = '
                    SELECT p.upc, p.description
                    FROM products AS p
                        INNER JOIN EWicItems AS e ON p.upc=e.upc
                    WHERE e.alias IS NULL
                        AND p.description LIKE ?
                    ORDER BY p.last_sold';
                $param = array('%' . $args->search . '%');
                $prep = $dbc->prepare($query);
                $res = $dbc->execute($prep, $param);
                while ($row = $dbc->fetchRow($res)) {
                    $ret[] = array(
                        'label' => $row['description'],
                        'value' => $row['upc'],
                    );
                }

                return $ret;

            default:
                return $ret;
        }
    }
}


