<?php

/* Copyright (C) 2019 Tobias Leupold <tobias.leupold@gmx.de>

   This file is part of the b8 package

   This program is free software; you can redistribute it and/or modify it
   under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation in version 2.1 of the License.

   This program 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 Lesser General Public
   License for more details.

   You should have received a copy of the GNU Lesser General Public License
   along with this program; if not, write to the Free Software Foundation,
   Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/

namespace b8\storage;

/**
 * A PostgreSQL storage backend
 *
 * @license LGPL 2.1
 * @package b8
 * @author Tobias Leupold <tobias.leupold@gmx.de>
 */

class pgsql extends storage_base
{

    private $pgsql = null;
    private $table = null;

    protected function setup_backend(array $config)
    {
        if (! isset($config['resource'])
            ) {

            throw new \Exception(pgsql::class . ": No valid pgsql object passed");
        }
        $this->pgsql = $config['resource'];

        if (! isset($config['table'])) {
            throw new \Exception(pgsql::class . ": No b8 wordlist table name passed");
        }
        $this->table = $config['table'];
    }

    protected function fetch_token_data(array $tokens)
    {
        $data = [];

        $escaped = [];
        foreach ($tokens as $token) {
            $escaped[] = pg_escape_string($this->pgsql, $token);
        }
        $result = pg_query($this->pgsql, 'SELECT token, count_ham, count_spam'
                                      . ' FROM ' . $this->table
                                      . ' WHERE token IN '
                                      . "('" . implode("','", $escaped) . "')");

        while ($row = pg_fetch_row($result)) {
            $data[$row[0]] = [ \b8\b8::KEY_COUNT_HAM  => $row[1],
                               \b8\b8::KEY_COUNT_SPAM => $row[2] ];
        }

        //$result->free_result();

        return $data;
    }

    protected function add_token($token, array $count)
    {
        // Check if statement has already been prepared:
        $result = pg_query_params($this->pgsql, 'SELECT name FROM pg_prepared_statements WHERE name = $1', array('add_token'));
        if (pg_num_rows($result) == 0) {
            $result = pg_prepare($this->pgsql, 'add_token', 'INSERT INTO ' . $this->table
                                       . '(token, count_ham, count_spam) VALUES($1, $2, $3)');
        }

        pg_execute($this->pgsql, 'add_token', array($token, $count[\b8\b8::KEY_COUNT_HAM],
                                          $count[\b8\b8::KEY_COUNT_SPAM]));
    }

    protected function update_token($token, array $count)
    {
        // Check if statement has already been prepared:
        $result = pg_query_params($this->pgsql, 'SELECT name FROM pg_prepared_statements WHERE name = $1', array('update_token'));
        if (pg_num_rows($result) == 0) {
            $result = pg_prepare($this->pgsql, 'update_token', 'UPDATE ' . $this->table
                                       . ' SET count_ham = $1, count_spam = $2 WHERE token = $3');
        }

        pg_execute($this->pgsql, 'update_token', array($count[\b8\b8::KEY_COUNT_HAM], $count[\b8\b8::KEY_COUNT_SPAM],
                                  $token));
    }

    protected function delete_token($token)
    {
        // Check if statement has already been prepared:
        $result = pg_query_params($this->pgsql, 'SELECT name FROM pg_prepared_statements WHERE name = $1', array('delete_token'));
        if (pg_num_rows($result) == 0) {
            $result = pg_prepare($this->pgsql, 'delete_token', 'DELETE FROM ' . $this->table . ' WHERE token = $1');
        }

        pg_execute($this->pgsql, 'delete_token', array($token));
    }

    protected function start_transaction()
    {
        pg_query($this->pgsql, 'BEGIN');
    }

    protected function finish_transaction()
    {
        pg_query($this->pgsql, 'COMMIT');
    }

}
