<?php
class SearchPage extends Page {
    private $terms = array();
    private $product_hits = array();
    private $user_hits = array();
    
    public function __construct() {
        parent::__construct();
        unset($_GET['page']);
        if(isset($_GET['q']) && !$_GET['q']) {
            unset($_GET['q']);
        }
        $this->terms = $this->translate_terms($_GET);
        if($this->terms) {
            $this->subtitle = 'Sökresultat';
            $hits = $this->do_search();
            if(isset($hits['product'])) {
                $this->product_hits = $hits['product'];
            }
            if(isset($hits['user'])) {
                $this->user_hits = $hits['user'];
            }
        }
    }
    
    private function do_search() {
        $out = array();
        if(!$this->terms) {
            return $out;
        }
        foreach(array('user', 'product') as $type) {
            $result = $this->search($type, $this->terms);
            if($result) {
                $out[$type] = $result;
            }
        }
        return $out;
    }

    private function search($type, $terms) {
        $matches = array();
        foreach(get_items($type) as $item) {
            if($result = $item->matches($terms, $this->ldap)) {
                $matches[] = array($item, $result);
            }
        }
        return $matches;
    }

    private function translate_terms($terms) {
        $matches = array();

        // If there is a q-query
        // and it contains a : character
        if(isset($terms['q']) && preg_match('/([^:]+):(.*)/',
                                            $terms['q'],
                                            $matches)) {
            // remove the q key
            unset($terms['q']);
            // insert the term, using whatever came before
            // the : as the key and whatever came after as the value
            $terms[$matches[1]] = $matches[2];
        }
        $translated = array();
        // Translate all keys into a standard format
        foreach($terms as $key => $values) {
            $newkey = $key;
            switch($key) {
                case 'q':
                    $newkey = 'fritext';
                    break;
                case 'tillverkare':
                case 'märke':
                    $newkey = 'brand';
                    break;
                case 'namn':
                    $newkey = 'name';
                    break;
                case 'faktura':
                case 'fakturanummer':
                    $newkey = 'invoice';
                    break;
                case 'serienummer':
                    $newkey = 'serial';
                    break;
                case 'tagg':
                case 'tags':
                    $newkey = 'tag';
                    break;
                case 'anteckning':
                    $newkey = 'note';
                    break;
                case 'e-post':
                case 'epost':
                case 'mail':
                    $newkey = 'email';
                    break;
                case 'status':
                    // Translate all status values into a standard format
                    $values = $this->translate_values($values);
                    break;
            }
            // Wrap the value in an array if it isn't one
            if(!is_array($values)) {
                $values = array($values);
            }
            // Make a SearchTerm object from each term
            foreach($values as $value) {
                // Check for flags
                $flag = SearchTerm::OPTIONAL;
                if(in_array($value[0], array(SearchTerm::MANDATORY,
                                             SearchTerm::OPTIONAL,
                                             SearchTerm::NEGATIVE))) {
                    $flag = $value[0];
                    $value = substr($value, 1);
                }
                // Collect the new SearchTerm
                $translated[] = new SearchTerm($newkey, $value, $flag);
            }
        }
        return $translated;
    }

    private function translate_values($value) {
        if(!is_array($value)) {
            $value = array($value);
        }
        $translated = array();
        foreach($value as $item) {
            $newitem = $item;
            switch($item) {
                case 'ute':
                case 'utlånad':
                case 'utlånat':
                case 'lånad':
                case 'lånat':
                    $newitem = 'on_loan';
                    break;
                case 'inne':
                case 'ledig':
                case 'ledigt':
                case 'tillgänglig':
                case 'tillgängligt':
                    $newitem = 'available';
                    break;
                case 'sen':
                case 'sent':
                case 'försenad':
                case 'försenat':
                case 'överdraget':
                    $newitem = 'overdue';
                    break;
                case 'skrotad':
                case 'skrotat':
                case 'slängd':
                case 'slängt':
                    $newitem = 'discarded';
                    break;
                case 'lagning':
                case 'reparation':
                    $newitem = 'service';
                    break;
            }
            $translated[] = $newitem;
        }
        return $translated;
    }
    
    protected function render_body() {
        $hidden = 'hidden';
        $terms = '';
        if($this->terms) {
            $hidden = '';
            foreach($this->terms as $term) {
                $key = $term->get_key();
                $flag = $term->get_flag();
                $query = $term->get_query();
                $fullterm = ucfirst($key).": ".$flag.$query;
                $terms .= replace(array('term' => $fullterm,
                                        'key' => $key,
                                        'value' => $flag.$query),
                                  $this->fragments['search_term']);
            }
        }
        $prod_table = 'Inga artiklar hittade.';
        if($this->product_hits) {
            $products = '';
            foreach($this->product_hits as $hit) {
                $products .= $this->build_product_row($hit[0], $hit[1]);
            }
            $prod_table = replace(array('rows' => $products,
                                        'type' => 'double'),
                                  $this->fragments['product_table']);
        }
        $user_table = 'Inga användare hittade.';
        if($this->user_hits) {
            $users = array();
            foreach($this->user_hits as $hit) {
                $users[] = $hit[0];
            }
            $user_table = $this->build_user_table($users);
        }

        print(replace(array('terms' => $terms,
                            'hidden' => $hidden,
                            'product_results' => $prod_table,
                            'user_results' => $user_table),
                      $this->fragments['search_form']));
    }
}

class SearchTerm {
    public const MANDATORY = '+';
    public const OPTIONAL = '~';
    public const NEGATIVE = '-';

    private $key;
    private $query;
    private $flag;

    public function __construct($key, $query, $flag=SearchTerm::OPTIONAL) {
        $this->key = $key;
        $this->query = $query;
        $this->flag = $flag;
    }

    public function get_key() {
        return $this->key;
    }

    public function get_query() {
        return $this->query;
    }

    public function get_flag() {
        return $this->flag;
    }

    public function is_optional() {
        if($this->flag == SearchTerm::OPTIONAL) {
            return true;
        }
        return false;
    }

    public function is_mandatory() {
        if($this->flag == SearchTerm::MANDATORY) {
            return true;
        }
        return false;
    }

    public function is_negative() {
        if($this->flag == SearchTerm::NEGATIVE) {
            return true;
        }
        return false;
    }
}
?>