<?php
/**
 * html gui elements
 * for bootstrap 3
 * CI SERVER GUI
 *
 * $oHtml=new htmlguielements();
 * 
 * echo $oHtml->getBox('error', 'errormessage');
 * echo $oHtml->getIcon('fa-pencil');
 * 
 * echo $oHtml->getLink(array(
 *     'href'=>'https://www.axel-hahn.de',
 *     'class'=>'btn btn-primary',
 *     'icon'=>'fa-close',
 *     'label'=>'linked text',
 * ));
 * 
 * echo $oHtml->getTabs(
 *     array(
 *         'tab 1'=>'Inhalt #1',
 *         'tab 2'=>'Inhalt #2',
 *     )
 * );
 * 
 * 
 * @author hahn
 */
class htmlguielements{
    
    var $aCfg=array(
        /*
        'buttonsOLD'=>array(
            // bootstrap defaults
            'primary'=>array('class'=>'btn-primary', 'icon'=>''),
            'success'=>array('class'=>'btn-success', 'icon'=>''),
            'info'=>array('class'=>'btn-info', 'icon'=>''),
            'warning'=>array('class'=>'btn-warning', 'icon'=>''),
            'danger'=>array('class'=>'btn-danger', 'icon'=>''),

            // custom buttons
            'close'=>array('class'=>'btn-danger', 'icon'=>'fa-close'),
            'error'=>array('class'=>'btn-danger', 'icon'=>'fa-bolt'),
            'ok'=>array('class'=>'btn-primary', 'icon'=>'fa-check'),
            
            // deploy actions and buttons
            'accept'=>array('class'=>''),
            'build'=>array('class'=>''),
            'cleanup'=>array('class'=>''),
            'deploy'=>array('class'=>'', 'icon'=>'glyphicon-forward'),
            'new'=>array('class'=>'', 'icon'=>'glyphicon-star-empty'),
            'overview'=>array('class'=>''),
            'phase'=>array('class'=>'', 'icon'=>'glyphicon-chevron-right'),
            'rollback'=>array('class'=>'', 'icon'=>'glyphicon-forward'),
            'setup'=>array('class'=>''),
            
        ),
        'iconsOLD'=>array(

            'menu'=>'fa-chevron-right',
            'overview'=>'fa-list',
            'project'=>'fa-book',
            'project-home'=>'fa-home',
            'projects'=>'fa-folder-o',
            'actions'=>'fa-check',
            
            'actionlog'=>'fa-list-ul',
            'accept'=>'glyphicon-forward',
            'build'=>'glyphicon-equalizer',
            'cleanup'=>'fa-trash',
            'checklang'=>'fa-check',
            'delete'=>'fa-close',
            'deploy'=>'glyphicon-forward',
            'filter'=>'glyphicon-filter',
            'new'=>'glyphicon-star-empty',
            'phase'=>'glyphicon-chevron-right',
            'rollback'=>'glyphicon-forward',
            'setup'=>'fa-cog',
            'login'=>'fa-lock',
            'user'=>'fa-user',
            
            'workflow'=>'fa-angle-double-right',
            'repository'=>'fa-database',
            'phase'=>'fa-flag',
            'package'=>'fa-cubes',
            'version'=>'fa-tag',
            'list'=>'fa-list',
            'raw-data'=>'fa-file-o',

            'back'=>'fa-chevron-left',
            
            'branch'=>'glyphicon-bookmark',
            'calendar'=>'glyphicon-calendar',
            'comment'=>'glyphicon-comment',
            'revision'=>'glyphicon-tag',

            'link-extern'=>'glyphicon-globe',
            
            'host'=>'fa-hdd-o',
            'hostgroup'=>'fa-sitemap',
            'templatefile'=>'fa-file-code-o',
            'targetfile'=>'fa-file-o',
            'replace'=>'fa-random',
            
            'sign-info'=>'',
            'sign-warning'=>'',
            'sign-error'=>'fa-bolt',
            'sign-ok'=>'',
        ),
         */
        'buttons'=>array(
            // bootstrap defaults
            'primary'=>array('class'=>'btn-primary', 'icon'=>''),
            'success'=>array('class'=>'btn-success', 'icon'=>''),
            'info'=>array('class'=>'btn-info', 'icon'=>''),
            'warning'=>array('class'=>'btn-warning', 'icon'=>''),
            'danger'=>array('class'=>'btn-danger', 'icon'=>''),

            // custom buttons
            'close'=>array('class'=>'btn-danger', 'icon'=>'fas fa-times'),
            'error'=>array('class'=>'btn-danger', 'icon'=>'fas fa-bolt'),
            'ok'=>array('class'=>'btn-primary', 'icon'=>'fas fa-check'),
            
            // deploy actions and buttons
            'accept'=>array('class'=>''),
            'build'=>array('class'=>''),
            'cleanup'=>array('class'=>''),
            'deploy'=>array('class'=>'', 'icon'=>'fas fa-forward'),
            'new'=>array('class'=>'', 'icon'=>'far fa-star'),
            'overview'=>array('class'=>''),
            'phase'=>array('class'=>'', 'icon'=>'fas fa-chevron-right'),
            'rollback'=>array('class'=>'', 'icon'=>'fas fa-forward'),
            'setup'=>array('class'=>''),
            
        ),
        'icons'=>array(

            'menu'=>'fas fa-chevron-right',
            'valuestore'=>'fa-solid fa-tags',
            'overview'=>'fas fa-list',
            'project'=>'fas fa-book',
            'project-home'=>'fas fa-home',
            'projects'=>'far fa-folder',
            'actions'=>'fas fa-check',
            
            'actionlog'=>'fas fa-list-ul',
            // 'accept'=>'fas fa-forward',
            'accept'=>'fas fa-check',
            'build'=>'fas fa-box-open',
            'checklang'=>'fas fa-check',
            'cleanup'=>'fas fa-broom',
            'close'=>'fas fa-times',
            'delete'=>'fas fa-trash',
            'deploy'=>'fas fa-forward',
            'deploy-configfile'=>'far fa-file-code',
            'deploy-rollout-plugin'=>'fas fa-plug',
            'filter'=>'fas fa-filter',
            'foreman'=>'fas fa-hard-hat',
            'gotop'=>'fas fa-arrow-up',
            'help'=>'fa-solid fa-life-ring',
            'login'=>'fa-solid fa-right-to-bracket',
            'new'=>'far fa-star',
            'phase'=>'fas fa-chevron-right',
            'poweroff'=>'fas fa-power-off',
            'refresh'=>'fas fa-sync',
            'rollback'=>'fas fa-forward',
            'setup'=>'fas fa-cog',
            'time'=>'far fa-clock',
            'waiting'=>'fas fa-clock',
            'user'=>'fas fa-user',
            'user-profile'=>'fa-regular fa-id-card',
            'user-group'=>'fa-regular fa-bookmark',
            'user-permission'=>'fa-solid fa-caret-right',
            
            'workflow'=>'fas fa-angle-double-right',
            'repository'=>'fas fa-database',
            'phase'=>'fas fa-flag',
            'package'=>'fas fa-cubes',
            'version'=>'fas fa-tag',
            'list'=>'fas fa-list',
            'raw-data'=>'far fa-file',
            'method'=>'fas fa-cogs',
            'url'=>'fas fa-globe-americas',

            'back'=>'fas fa-chevron-left',
            
            'branch'=>'fas fa-bookmark',
            'calendar'=>'far fa-calendar',
            'comment'=>'far fa-comment',
            'revision'=>'fas fa-tag',

            'link-extern'=>'fas fa-globe-americas',
            
            'host'=>'far fa-hdd',
            'hostgroup'=>'fas fa-sitemap',
            'file-any'=>'far fa-file',
            'file-archive'=>'far fa-file-archive',
            'file-code'=>'far fa-file-code',
            'file-meta'=>'far fa-file',
            'file-template'=>'far fa-file-alt',
            'file-target'=>'fas fa-file-upload',
            'replace'=>'fas fa-random',
            
            'box-up'=>'fa-chevron-up',
            'box-down'=>'fa-chevron-down',

            'sign-info'=>'fa-solid fa-info',
            'sign-warning'=>'fa-solid fa-exclamation',
            'sign-error'=>'fas fa-bolt',
            'sign-ok'=>'fas fa-check',
        ),
    );
    
    public function __construct() {
        return true;
    }
    
    // ----------------------------------------------------------------------
    // helper function
    // ----------------------------------------------------------------------
    
    /**
     * add an html attribute if the attribute exists as a key
     * @param string  $sAttribute  html attribute to add
     * @param string  $aData       item array
     * @param string  $sDefault    use default if key does not exists
     * @return string
     */
    public function addAttributeFromKey($sAttribute, $aData, $sDefault=''){
        return (isset($aData[$sAttribute]) 
                ? $this->addAttribute($sAttribute, $aData[$sAttribute])
                : $this->addAttribute($sAttribute, $sDefault)
                );
    }
    
    /**
     * add an html attribute if value is not empty
     * @param string  $sAttribute  html attribute to add
     * @param string  $sValue      value of attribute
     * @return string
     */
    public function addAttribute($sAttribute, $sValue){
        return ($sValue ? ' '.$sAttribute.'="'.$sValue.'"' : '' );
    }
    
    /**
     * get html attributes as string from all keys of given hash
     * 
     * @param array $aItem
     * @return string
     */
    public function addAllAttributes($aItem){
        $sReturn='';
        foreach (array_keys($aItem) as $sKey){
            $sReturn.=$this->addAttributeFromKey($sKey, $aItem);
        }
        return $sReturn;
    }
    
    // ----------------------------------------------------------------------
    // low level
    // ----------------------------------------------------------------------
    
    /**
     * get html code for icon; glypphicons and font-awesome is supported
     * 
     * @param string $sLabel  label of icon
     * @return string
     */
    public function getIcon($sLabel){
        if(!$sLabel){
            return '';
        }
        $sPrefix=(
                strpos($sLabel, 'glyphicon-')===0 ? 'glyphicon' 
                : ( strpos($sLabel, 'fa-')===0 ? 'fa' : '')
                );
        // if(!$sPrefix){
        if(isset($this->aCfg['icons'][$sLabel])){
            return $this->getIconByType($sLabel);
        }
        return '<i'.$this->addAttribute('class', ($sPrefix ? $sPrefix . ' ' : '').$sLabel).'></i> ';
    }
    /**
     * get html code for icon; glypphicons and font-awesome is supported
     * 
     * @param string $sLabel  label of icon
     * @return string
     */
    public function getIconClass($sLabel){
        if(!$sLabel){
            return '';
        }
        if(isset($this->aCfg['icons'][$sLabel])){
            return $this->aCfg['icons'][$sLabel];
        }
        $sPrefix=(
                strpos($sLabel, 'glyphicon-')===0 ? 'glyphicon' 
                : ( strpos($sLabel, 'fa-')===0 ? 'fa' : '')
                );
        return ($sPrefix ? $sPrefix . ' ' : '').$sLabel;
    }
    
    /**
     * get a default icon from config
     * @param string  $sType  icon type
     * @return array 
     */
    public function getIconByType($sType){
        return (isset($this->aCfg['icons'][$sType])
            ? $this->getIcon($this->aCfg['icons'][$sType])
            : ''
        );
    }

    /**
     * get html code for icon; glypphicons and font-awesome is supported
     * 
     * @param array $aItem  array with link attributes; href for target; "label" and "icon" 
     * @return string
     */
    public function getLink($aItem){
        
        $sHref=$this->addAttributeFromKey('href', $aItem, '#');
        $sLabel=(isset($aItem['icon']) ? $this->getIcon($aItem['icon']): '')
            .(isset($aItem['label']) ? $aItem['label'] : '');
        
        foreach(array('href', 'icon', 'label') as $sKey){
            if (isset($aItem[$sKey])){
                unset($aItem[$sKey]);
            }
        }
        
        $sReturn='<a'.$sHref;
        $sReturn.=$this->addAllAttributes($aItem);
        $sReturn.='>'
                .$sLabel
                .'</a>';
        return $sReturn;
    }
    
    /**
     * add default css classes and colors based on $aItem['type'] and the
     * local default settings in $this->aCfg
     * 
     * @param array  $aItem
     * @return array 
     */
    protected function _getButtonattributesByType($aItem){
        $aReturn=$aItem;
        if (isset($this->aCfg['buttons'][$aItem['type']])){
            $sClass=$this->aCfg['buttons'][$aItem['type']]['class'];
            $aReturn['class'].=$sClass ? ' '.$sClass : '';
            
            // icon priority:
            // given in param --> icon in button config --> icon in icon config
            $aReturn['icon']=$aReturn['icon'] ? $aReturn['icon'] : 
                ( $this->aCfg['buttons'][$aItem['type']]['icon'] 
                    ? $this->aCfg['buttons'][$aItem['type']]['icon'] 
                    : ( 
                        isset($this->aCfg['icons'][$aItem['type']]) 
                            ? $this->aCfg['icons'][$aItem['type']] 
                            : ''
                    )
                );
        }
        return $aReturn;
    }


    /**
     * get html code for icon; glypphicons and font-awesome is supported
     * 
     * @param array $aItem  array with link attributes; href for target; "label" and "icon" 
     * @return string
     */
    public function getLinkButton($aItem){
        foreach(array('class', 'icon') as $sKey){
            if (!isset($aItem[$sKey])){
                $aItem[$sKey]='';
            }
        }
        // if not class "btn" was added: add "btn" 
        // if not class "btn-[something]" was added: add "btn-default" 
        $sClass=$aItem['class'];
        $sClass=(strstr($sClass, 'btn-') ? '' : 'btn-default ').$sClass;
        $sClass=(strstr($sClass, 'btn ') ? '' : 'btn ').$sClass;
        $aItem['class']=$sClass;
        
        if (isset($aItem['type'])){
            $aItem=$this->_getButtonattributesByType($aItem);
            unset($aItem['type']);
        }
        // $aItem['label'].=' -> '.$sClass;
        return $this->getLink($aItem);
    }

    // ----------------------------------------------------------------------
    // gui elements
    // ----------------------------------------------------------------------

    /**
     * get html code of a div around a message
     * @param string $sWarnlevel one of error|success|info|warning to get a colored box
     * @param string $sMessage   message text
     * @return string
     */
    public function getBox($sWarnlevel, $sMessage) {
        $aCfg = array(
            "error" => array("class" => "alert alert-danger", "prefix" => t("error")),
            "success" => array("class" => "alert alert-success", "prefix" => t("success")),
            "info" => array("class" => "alert alert-info", "prefix" => t("info")),
            "warning" => array("class" => "alert alert-warning", "prefix" => t("warning")),
        );
        $sClass = "";
        $sPrefix = "";
        if (isset($aCfg[$sWarnlevel])) {
            $sClass = $aCfg[$sWarnlevel]["class"];
            $sPrefix = $aCfg[$sWarnlevel]["prefix"];
            $sMessage = '<strong>' . $aCfg[$sWarnlevel]["prefix"] . '</strong> ' . $sMessage;
        }
        return '<div'.$this->addAttribute('class', $sClass).'>' . $sMessage . '</div>';
    }
    
    /**
     * get html code for tabs with content
     * 
     * @staticvar int $iCounter  internal counter for tabs ans content
     * @param array  $aTabData  tab data; key is the tab label; value the content of its tab
     * @return string
     */
    public function getNav__UNUSED($aTabData){
        $sTabs='';
        $sContent='';
        
        static $iCounter=0;
        $iTab=0;
        
        if (!is_array($aTabData) || !count($aTabData)){
            return false;
        }
        $sNavType=$aTabData['options']['type']; // "tabs" or "pills"
        $sNavCss='nav nav-'.$sNavType;
        if (isset($aTabData['options']['stacked']) && $aTabData['options']['stacked']){
            $sNavCss.=' nav-stacked';
        }
        if (isset($aTabData['options']['justified']) && $aTabData['options']['justified']){
            $sNavCss.=' nav-justified';
        }
        $sNavType=$aTabData['options']['justified'];
        foreach ($aTabData['tabs'] as  $sTabLabel=>$sTabContent){
            $iCounter++;
            $iTab++;
            $sId="tab-generated-$iCounter";
            $sTabs.= ($iTab==1 ?  '<li class="active"' : '<li')
                . ' role="presentation">'
                . '<a href="#'.$sId.'" data-toggle="tab">' . $sTabLabel . '</a></li>'
                ;
            $sContent.='<div class="tab-pane'
                    .($iTab==1 ?  ' active' : '')
                    .'" id="'.$sId.'">'
                    .$sTabContent
                    .'</div>'
                    ;
        }
        return '<div class="tabbable">'
                . '<ul class="'.$sNavCss.'">'. $sTabs.'</ul>'
                . '<div class="tab-content">'.$sContent.'</div>'
                . '</div>';
    }

    /**
     * get html code for a table
     * 
     * @param array $aTabledata  array with subkeys "header" and "body"
     * @return string
     */
    public function getTable($aTabledata) {
        $sTHead='';
        $sTBody='';
        if (isset($aTabledata['body'])){
            foreach ($aTabledata['body'] as $aRow){
                $sTBody.='<tr>';
                foreach ($aRow as $sItem){
                    $sTBody.='<td>'.$sItem.'</td>';
                }
                $sTBody.='</tr>';
            }
        }
        if (isset($aTabledata['header'])){
            foreach ($aTabledata['header'] as $sItem){
                $sTHead.='<th>'.$sItem.'</th>';
            }
        }
        return '<table class="table" style="width: auto;">'
            .($sTHead ? '<thead>'.$sTHead.'</thead>' : '')
            .($sTBody ? '<tbody>'.$sTBody.'</tbody>' : '')
            .'</table>'
            ;
    }
        
}