<?php
/**
 * html gui elements
 * for bootstrap
 * see http://dev.ci.iml.unibe.ch:8002/deployment/all/htmltest/
 *
 * $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(
        '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'=>'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'=>''),
            
        ),
        'icons'=>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',
            
            'host'=>'fa-hdd-o',
            'hostgroup'=>'fa-sitemap',
            'templatefile'=>'fa-file-code-o',
            'targetfile'=>'fa-file-o',
            'replace'=>'fa-random',            
        ),
    );
    
    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 (array_key_exists($sAttribute, $aData) 
                ? $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){
            return $this->getIconByType($sLabel);
        }
        return '<i'.$this->addAttribute('class', ($sPrefix ? $sPrefix . ' ' : '').$sLabel).'></i> ';
    }
    
    /**
     * get a default icon from config
     * @param string  $sType  icon type
     * @return array 
     */
    public function getIconByType($sType){
        return (array_key_exists($sType, $this->aCfg['icons'])
            ? $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=(array_key_exists('icon', $aItem) ? $this->getIcon($aItem['icon']): '')
            .(array_key_exists('label', $aItem) ? $aItem['label'] : '');
        
        foreach(array('href', 'icon', 'label') as $sKey){
            if (array_key_exists($sKey, $aItem)){
                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 (array_key_exists($aItem['type'], $this->aCfg['buttons'])){
            $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'] 
                    : ( array_key_exists($aItem['type'], $this->aCfg['icons']) ? $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 (!array_key_exists($sKey, $aItem)){
                $aItem[$sKey]='';
            }
        }
        $aItem['class'].='btn btn-default';
        
        if (array_key_exists('type', $aItem)){
            $aItem=$this->_getButtonattributesByType($aItem);
            unset($aItem['type']);
        }
        
        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 (array_key_exists($sWarnlevel, $aCfg)) {
            $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($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 (array_key_exists('stacked', $aTabData['options']) && $aTabData['options']['stacked']){
            $sNavCss.=' nav-stacked';
        }
        if (array_key_exists('justified', $aTabData['options']) && $aTabData['options']['justified']){
            $sNavCss.=' nav-justified';
        }
        $sNavType=$aTabData['options']['justified'];
        foreach ($aTabData['tabs'] as  $sTabLabel=>$sTabContent){
            $iCounter++;
            $iTab++;
            $sId="tab${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 (array_key_exists('body', $aTabledata)){
            foreach ($aTabledata['body'] as $aRow){
                $sTBody.='<tr>';
                foreach ($aRow as $sItem){
                    $sTBody.='<td>'.$sItem.'</td>';
                }
                $sTBody.='</tr>';
            }
        }
        if (array_key_exists('header', $aTabledata)){
            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>'
            ;
    }
        
}
