<?php

/**
 * class to log all project actions, ie. build, deploy etc.
 *
 * @author hahn
 */
class Actionlog {

    private $_aLoglevels = array("info", "warning", "error", "success"); // array of valid loglevels
    private $_sIP = false;
    private $_sUser = false;
    private $_sProject = false;
    private $_sCreate = '
        CREATE TABLE "logs" (
          `id` INTEGER PRIMARY KEY  AUTOINCREMENT  NOT NULL  UNIQUE ,
          `time` DATETIME,
          `loglevel` TEXT,
          `ip` TEXT,
          `user` TEXT,
          `project` TEXT,
          `action` TEXT,
          `message` TEXT
        )';

    /**
     * constructor - sets internal environment variables and checks existence 
     * of the database
     * @global array $aConfig    settings
     * @param  string $sProject  project ID
     */
    public function __construct($sProject = false) {
        global $aConfig;

        $this->_dbfile = $aConfig['appRootDir'] . '/database/logs.db';
        if (!file_exists($this->_dbfile)) {
            $this->_createDb();
        }

        $this->_sProject = $sProject;
        if (isset($_SERVER) && is_array($_SERVER) && array_key_exists("PHP_AUTH_USER", $_SERVER) && $_SERVER["PHP_AUTH_USER"]
        ) {
            $this->_sIP = $_SERVER["REMOTE_ADDR"];
            $this->_sUser = $_SERVER["PHP_AUTH_USER"] . " (web)";
        } else {
            $this->_sIP = 'local';
            $this->_sUser = get_current_user() . " (system)";
        }
    }

    /**
     * create sqlite database - called in constructor if the file does not exist
     */
    private function _createDb() {
        return $this->_makeQuery($this->_sCreate);
    }

    /**
     * execute a sql statement
     * @param string $sSql sql statement
     * @return database object
     */
    private function _makeQuery($sSql) {
        // $this->_log(__FUNCTION__."($sSql)");
        // echo "<pre>$sSql</pre>";
        $db = new PDO("sqlite:" . $this->_dbfile);
        $result = $db->query($sSql);
        $db = NULL;
        return $result;
    }

    /**
     * add a log message
     * @param string $sMessage   message
     * @param string $sAction    project action; i.e. build, deploy, ...
     * @param string $sLoglevel  loglevel
     */
    public function add($sMessage, $sAction = "", $sLoglevel = "info") {
        if (array_search($sLoglevel, $this->_aLoglevels) === false) {
            die(__class__ . ": loglevel $sLoglevel is invalid");
        }
        $sql = "INSERT INTO `logs` (`time`, `loglevel`, `ip`, `user`, `project` ,`action`, `message`)
          VALUES(
            '" . date("Y-m-d H:i:s") . "',
            '" . $sLoglevel . "',
            '" . $this->_sIP . "',
            '" . $this->_sUser . "',
            '" . $this->_sProject . "',
            '" . $sAction . "',
            '" . $sMessage . "'
          );
        ";
        // echo $sql . "<br>";
        $this->_makeQuery($sql);
    }

    /**
     * get log data
     * @param array $aFilter with the following keys:
     *   'project' - filter by project; will be mixed with where (see next key)
     *   'where' - where clausel - part behind "WHERE "
     *   'order' - order clausel - part behind "ORDER BY "; default is "id DESC" (order by newest entries)
     *   'limit' - limit clausel - part behind "LIMIT "
     * @return array
     */
    public function getLogs($aFilter = array()) {
        // var_dump(R::findAll( 'log' ));
        $aReturn = array();

        $sSql = 'SELECT * from logs ';
        $sWhere = false;
        if (array_key_exists("where", $aFilter) && $aFilter["where"]) {
            $sWhere.=' WHERE (' . $aFilter["where"] . ') ';
        }
        if (array_key_exists("project", $aFilter) && $aFilter["project"]) {
            $sProjectWhere = '`project`="' . $aFilter["project"] . '"';
            $sWhere.= $sWhere ? ' AND ' . $sProjectWhere : 'WHERE ' . $sProjectWhere;
        }
        $sSql.=$sWhere;

        if (array_key_exists("order", $aFilter) && $aFilter["order"]) {
            $sSql.=' ORDER BY ' . $aFilter["order"];
        } else {
            $sSql.=' ORDER BY id DESC ';
        }
        if (array_key_exists("limit", $aFilter) && $aFilter["limit"]) {
            $sSql.=' LIMIT ' . $aFilter["limit"];
        }

        foreach ($this->_makeQuery($sSql) as $row) {
            for ($i = 0; $i <= 7; $i++) {
                unset($row[$i]);
            }
            $aReturn[] = $row;
        }
        return $aReturn;
    }

    /**
     * render html code for a table with logs. The filter will be sent to
     * getLogs method.
     * @param array $aFilter with the following keys:
     *   'project' - filter by project; will be mixed with where (see next key)
     *   'where' - where clausel - part behind "WHERE "
     *   'order' - order clausel - part behind "ORDER BY "; default is "id DESC" (order by newest entries)
     *   'limit' - limit clausel - part behind "LIMIT "
     * @return string
     */
    public function renderLogs($aFilter = array()) {
        $sReturn = "";

        static $bWasShown;
        if ($bWasShown)
            return " ";

        $bWasShown = true;
        $aData = $this->getLogs($aFilter);
        if (!count($aData)) {
            $sReturn = t("class-actionlog-nolog");
        } else {
            $sReturn.='<thead><tr>';
            foreach (array_keys($aData[0]) as $sRow) {
                $sReturn.='<th>' . $sRow . '</th>';
            }
            $sReturn.='</tr></thead>';
            $sReturn.='<tbody>';
            foreach ($aData as $aRow) {
                $sReturn.='<tr class="tractionlogs loglevel-' . $aRow["loglevel"] . ' ' . $aRow["project"] . '">';
                foreach ($aRow as $sValue) {
                    $sReturn.='<td>' . $sValue . '</td>';
                }
                $sReturn.='</tr>';
            }
            $sReturn.='</tbody>';
            $sReturn = '
                    <i class="icon-filter"></i>
                    ' . t("overview-textsearch") . ':
                    <input type="text" id="efilterlogs" name="efilterlogs"
                        style="width: 150px;"
                        onchange="filterLogTable();"
                        onKeypress="filterLogTable(); "
                        onKeyup="filterLogTable(); "
                        title="' . t("overview-textsearch-hint") . '"
                        >
                        
                    <i class="icon-list-alt"></i>
                    <a href="/deployment/all/setup/actionlog/">all</a><br>
                    
                    <table class="table">' . $sReturn . '</table>';
        }

        $sReturn = '<strong>'
                . '<button onclick="setLogVisibility(\'block\');"  id="btnShowLogs" class="btnLogs"><b class="icon-chevron-right"></b> </button>'
                . '<button onclick="setLogVisibility(\'none\');"   id="btnHideLogs" class="btnLogs"><b class="icon-chevron-down"></b> </button>'
                . ' ' . t("class-actionlog-title") 
                . '</strong>'
                
                . '<div id="divActionlogs">'
                . '<p>' . t("class-actionlog-filter") . ': ' . print_r($aFilter, true) . ')</p>'
                . $sReturn
                . '</div>
                <script>
                
                function getLogVisibility(){
                    var sReturn=localStorage.getItem("bActionlogsVisible");
                    sReturn=(sReturn=="block")?"block":"none";
                    return sReturn;
                }

                function setLogVisibility(sVisibility){
                    localStorage.setItem("bActionlogsVisible", sVisibility);
                    $("#divActionlogs").css("display", sVisibility);
                    $(".btnLogs").css("display", "none");
                    if (sVisibility=="block"){
                        $("#btnHideLogs").css("display", "inline");
                    } else {
                        $("#btnShowLogs").css("display", "inline");
                    }
                }
                /**
                * filter table and tiles by filtertext
                */
                function filterLogTable(){
                    var sSearch=$("#efilterlogs").val();
                    var Regex = new RegExp(sSearch, "i");
                    $(".tractionlogs").each(function() {
                        sVisible="none";
                        if ( Regex.exec(this.innerHTML)) {
                            sVisible="";
                        }
                        $(this).css("display", sVisible);
                    });
                    return false;
                }
                setLogVisibility(getLogVisibility());
                </script>';

        return $sReturn;
    }

}