<?php
/**
 * Pimcore
 *
 * This source file is subject to the GNU General Public License version 3 (GPLv3)
 * For the full copyright and license information, please view the LICENSE.md and gpl-3.0.txt
 * files that are distributed with this source code.
 *
 * @copyright  Copyright (c) 2009-2016 pimcore GmbH (http://www.pimcore.org)
 * @license    http://www.pimcore.org/license     GNU General Public License version 3 (GPLv3)
 */

namespace Pimcore\Db;

class Profiler extends \Zend_Db_Profiler
{
    /**
     * The original label for this profiler.
     * @var string
     */
    protected $_label = null;

    /**
     * The label template for this profiler
     * @var string
     */
    protected $_label_template = '%label% (%totalCount% @ %totalDuration% sec)';

    /**
     * The message envelope holding the profiling summary
     * @var \Zend_Wildfire_Plugin_FirePhp_TableMessage
     */
    protected $_message = null;

    /**
     * The total time taken for all profiled queries.
     * @var float
     */
    protected $_totalElapsedTime = 0;

    /**
     * @var int
     */
    protected $_totalQueries = 0;

    /**
     * @var resource
     */
    protected $logFile;

    /**
     * @var int
     */
    protected $connectionId;

    /**
     * @var array
     */
    protected $queries = array();

    /**
     * @param null $label
     */
    public function __construct($label = null)
    {
        $this->_label = $label;
        if(!$this->_label) {
            $this->_label = "Pimcore\\Db\\Profiler";
        }
    }

    /**
     * Enable or disable the profiler.  If $enable is false, the profiler
     * is disabled and will not log any queries sent to it.
     *
     * @param  boolean $enable
     * @return \Zend_Db_Profiler Provides a fluent interface
     */
    public function setEnabled($enable)
    {
        parent::setEnabled($enable);
        return $this;
    }

    /**
     * Intercept the query end and log the profiling data.
     *
     * @param  integer $queryId
     * @throws \Zend_Db_Profiler_Exception
     * @return void
     */
    public function queryEnd($queryId)
    {
        $state = parent::queryEnd($queryId);

        if (!$this->getEnabled() || $state == self::IGNORED) {
            return;
        }
        
        $profile = $this->getQueryProfile($queryId);
        $this->_totalElapsedTime += $profile->getElapsedSecs();
        $this->_totalQueries++;

        $logEntry = $profile->getQuery() . " | " . implode(",",$profile->getQueryParams());
        \Logger::debug($logEntry, [
            "connection" => $this->getConnectionId(),
            "queryNum" => $this->_totalQueries,
            "time" => (string)round($profile->getElapsedSecs(),5)
        ]);

        $this->queries[] = array(
            "time" => $profile->getElapsedSecs(),
            "query" => $profile->getQuery() . " | " . implode(",",$profile->getQueryParams())
        );
    }

    /**
     * 
     */
    public function __destruct() {
        if(is_resource($this->logFile)) {

            // write the total time at the end
            $message = "\n\n\n--------------------\n";
            $message .= "Total Elapsed Time: ". (string)round($this->_totalElapsedTime,5) . "\n";
            $message .= "Total Queries: " . $this->_totalQueries . "\n";
            $message .= "Top Queries: \n";

            uasort($this->queries, function ($x, $y) {
                $a = $x["time"];
                $b = $y["time"];

                if ($a == $b) {
                    return 0;
                }
                return ($b < $a) ? -1 : 1;
            });

            $count = 0;
            foreach ($this->queries as $key => $value) {
                $count++;
                if($count > 5) {
                    break;
                }

                $message .= "#" . $key . ":  " . (string)round($value["time"],5) . " | " . $value["query"] . "\n";
            }
            $message .= "\n";

            $message .= "\n--------------------\n\n";


            fwrite($this->logFile, $message);

            fclose($this->logFile);    
        }
    }

    /**
     * Update the label of the message holding the profile info.
     *
     * @return void
     */
    protected function updateMessageLabel()
    {
        if (!$this->_message) {
            return;
        }
        $this->_message->setLabel(str_replace(array('%label%',
                                                    '%totalCount%',
                                                    '%totalDuration%'),
                                              array($this->_label,
                                                    $this->getTotalNumQueries(),
                                                    (string)round($this->_totalElapsedTime,5)),
                                              $this->_label_template));
    }

    /**
     * @param int $connectionId
     */
    public function setConnectionId($connectionId)
    {
        $this->connectionId = $connectionId;
    }

    /**
     * @return int
     */
    public function getConnectionId()
    {
        return $this->connectionId;
    }
}
