<?php
//************************************************
//Function Extracted from aim to read custom tag content
 function Is_ASSOC($arr){
    return array_keys($arr) !== range(0, count($arr) - 1);
}

 function IsAssoc($arr){
    return Is_ASSOC($arr);
}


//ReadFileInsertValue
//Method to insert value in place holder
 function ReadFileInsertValue($Markup ="",$placehoder="",$value=""){
    // $Markup;
   if(trim($placehoder) == ""){
       return $Markup;
   }
   //if $value is url, resolve the protocol
  // $value = UrlPrep($value);
   return str_replace('{{'.$placehoder.'}}',$value,$Markup);
}

//#ReadFileIterateRegion
//Method to get iterating region
 function ReadFileIterateRegion($Markup="",$placehoder=""){
    //get the looping string (Iterating Region)
                     $Fpos = strpos($Markup,'{{'.$placehoder.'}}');//get first ocurence
                     
                     if($Fpos !== FALSE){
                                              
                       $StartPos = $Fpos + strlen('{{'.$placehoder.'}}'); //get the loopstring startpos
                       //get the last ocurence
                       $Lpos = strpos($Markup,'{{'.$placehoder.'}}',$StartPos);
                       if($Fpos != $Lpos){ //if the ending label found
                         
                         $loopstrlen = $Lpos - $StartPos; //get the lenght of the loopstr
                        // echo $loopstrlen;
                          return substr($Markup,$StartPos,$loopstrlen); 
                          //get the loopstring
                         // echo $loopstr;
                       }else{
                           //if ending label not found take the rest string
                           return substr($Markup,$StartPos);
                       }
                     }else{
                         return NULL; //no loop region found
                     }
 }

 //#ReadFileIterateRegionName
//Method to get iterating region and the region name
 function ReadFileIterateRegionName($Markup="",$placehoder=""){
    //get the looping string (Iterating Region)
                     $Fpos = strpos($Markup,'{{'.$placehoder." ");//get first ocurence
                        $Fpos = $Fpos === false?strpos($Markup,'{{'.$placehoder."}}"):$Fpos;
                        $name = "";
                     if($Fpos !== FALSE){
                         $SeenLen = strlen('{{'.$placehoder);
                        //try to get the closing brackets
                        $FposEnd =  strpos($Markup,'}}',$Fpos + $SeenLen - 1);//get closing
                        if($FposEnd !== false){
                            //get the name
                            $nameLen = $FposEnd - ($Fpos + $SeenLen);
                            if($nameLen > 0){
                                $name = substr($Markup,$Fpos + $SeenLen,$nameLen);
                            }
                            

                           //get the last ocurence
                            $Lpos = strpos($Markup,'{{'.$placehoder.'}}',$FposEnd);
                            
                            $StartPos = $FposEnd + 2; //get the loopstring startpos
                            
                            if($Lpos !== false && $StartPos < $Lpos){ //if the ending label found
                                
                                $loopstrlen = $Lpos - $StartPos; //get the lenght of the loopstr
                                // echo $loopstrlen;
                                return array("Body"=>substr($Markup,$StartPos,$loopstrlen),"Name"=>$name); 
                                //get the loopstring
                                // echo $loopstr;
                            }else{
                                //if ending label not  found take the rest string
                                return array("Body"=>substr($Markup,$StartPos),"Name"=>$name);
                            }
                        }else{
                            return array("Body"=>"","Name"=>""); //no loop region found  
                        }
                      
                     }else{
                         return array("Body"=>"","Name"=>""); //no loop region found
                     }
 }

 

 //#ProccessDirectAddressing
  function InsertDirectAddress($ValueArr=array(),$Markup="",$placehoder=""){
     if(is_array($ValueArr)){
        foreach($ValueArr as $Key => $Val){
                if(is_string($Val) || is_numeric($Val)){ //if replacable
                    if($placehoder != ""){
                        $Markup = str_replace('{{'.$placehoder.'->'.$Key.'}}',$Val,$Markup);
                    }
                }else if(is_array($Val)){
                    $nplacehoder = $placehoder == ""?$Key:$placehoder.'->'.$Key;
                    $Markup = InsertDirectAddress($Val,$Markup,$nplacehoder);
                }
            }
     }
     
     return $Markup;
 }

 //#ReadFileProccessArrayValue
 //Method to Handle array values
  function ReadFileProccessArrayValue($ValueArr=array(),$Markup="",$placehoder="",$ParentPlaceholder=""){//str_replace('{{'.$placehoder.'}}','',$Markup);
 if(trim($Markup) == "") return "";

if(trim($placehoder) == ""){
     //if place holder is numeric or not set
//echo $placehoder;
if(trim($ParentPlaceholder) == "" || is_numeric($ParentPlaceholder))return $Markup; //if the parent placeholder is also not set, meaning nothing to replace return back the markup
//use the parent placeholder
$placehoder = $ParentPlaceholder;
}


//process all direct addressing values
$Markup = InsertDirectAddress($ValueArr,$Markup,$placehoder);

$filcont = $Markup;
//get the IterateRegion
//$IterateRegion = ReadFileIterateRegion($Markup,$placehoder);
$IterateRegion = ReadFileIterateRegion($filcont,$placehoder);
//echo $IterateRegion;

//if(trim($IterateRegion) == "")return str_replace('{{'.$placehoder.'}}','',$Markup); //if no iteration region
while(!is_null($IterateRegion)){
$FormedMarkup = ""; //reset the formed markup for the new place holder seen
//if no data sent for the iteration region
if((is_array($ValueArr) && count($ValueArr) < 1) || (is_object($ValueArr) && isset($ValueArr->num_row) && $ValueArr->num_row < 1) || trim($IterateRegion) == "") {
    //return str_replace('{{'.$placehoder.'}}'.$IterateRegion.'{{'.$placehoder.'}}','',$Markup); //if no array item found clear the placeholder and the IterationRegion
    $filcont = str_replace('{{'.$placehoder.'}}'.$IterateRegion.'{{'.$placehoder.'}}','',$filcont); //if no array item found clear the placeholder and the IterationRegion
    $IterateRegion = ReadFileIterateRegion($filcont,$placehoder);
    continue;
}

//Check for Option 1
//Numeric iteration
if(is_array($ValueArr) && count($ValueArr) == 1){
if(!Is_ASSOC($ValueArr) && is_numeric($ValueArr[0])){ //if no key set and the value is numeric
   for($s=1;$s<=$ValueArr[0];$s++){ //concatinate the IterateRegion in $ValueArr[0] times and also display the increament if the increament placeholder is set
      $FormedMarkup .= str_replace(array('{{$}}','{{$'.$placehoder.'}}'),$s,$IterateRegion);
   }
  // $filcont = str_replace('{{'.$placehoder.'}}'.$IterateRegion.'{{'.$placehoder.'}}',$FormedMarkup,$Markup);
   $filcont = str_replace('{{'.$placehoder.'}}'.$IterateRegion.'{{'.$placehoder.'}}',$FormedMarkup,$filcont);
 //return $filcont;
 $IterateRegion = ReadFileIterateRegion($filcont,$placehoder);
 continue;
}

}

//Option 2 and 3
//Stop here, trying to code, if the current array is associate, loop through the values to set the replacement if value is string else resend into array proccessor, using the associate key as place holder and curent iterate region as markup.

//else if current array is not associate, loop trough each value, and set 
if((is_array($ValueArr) && !Is_ASSOC($ValueArr)) || (is_object($ValueArr) && isset($ValueArr->num_rows))){ //if not associate array
//echo $placehoder. " not associate <br>";
$cnter = 1; //for increament display
if(is_array($ValueArr)){ //if an array
    foreach($ValueArr as $rval){
    if(!is_array($rval)){ //if current value is not an array replace placeholder in the iteration region markup
        $FormedMarkup .= ReadFileInsertValue(str_replace(array('{{$}}','{{$'.$placehoder.'}}'),$cnter,$IterateRegion),"?",$rval);
        
    }else{
        //loop through each item and replace then in iterationRegion, before concatinating the resultant IterationRegion to FormedMarkup
        //$ValueArr=array(),$Markup="",$placehoder="",$ParentPlaceholder=""
        
        $FormedMarkup .= ReadFileProccessArrayValue($rval,"{{".$placehoder."}}".str_replace(array('{{$}}','{{$'.$placehoder.'}}'),$cnter,$IterateRegion)."{{".$placehoder."}}",$placehoder);
    }
    $cnter++;
    }
}else{ //if database object
    
  while($rval = $ValueArr->fetch_assoc()){
   // exit($rval['SurName']);
   //$rval = ["SurName"=>"aaaa","FirstName"=>"dddd","OtherNames"=>"ssss","RegNo"=>"dddd","Rst"=>"jhdd"];
    $FormedMarkup .= ReadFileProccessArrayValue($rval,"{{".$placehoder."}}".str_replace(array('{{$}}','{{$'.$placehoder.'}}'),$cnter,$IterateRegion)."{{".$placehoder."}}",$placehoder);
    $cnter++;
  }
}

}else{ //if an associate array

$internalIterationRegion = $IterateRegion;
//check if the $ValueArr is array

   foreach($ValueArr as $rkey => $rval){
 
 if(is_array($rval) || is_object($rval)){//if valu not array
 //if($placehoder=="Colored"){
    // echo "$rkey=>$rval <br/>";
 //}
 
 $internalIterationRegion =   ReadFileProccessArrayValue($rval,$internalIterationRegion,$rkey,$placehoder);
 }else{
   $internalIterationRegion = ReadFileInsertValue($internalIterationRegion,$rkey,$rval);
 }
}


$FormedMarkup = $internalIterationRegion;
}
 
//$filcont = str_replace('{{'.$placehoder.'}}'.$IterateRegion.'{{'.$placehoder.'}}',$FormedMarkup,$Markup);
$filcont = str_replace('{{'.$placehoder.'}}'.$IterateRegion.'{{'.$placehoder.'}}',$FormedMarkup,$filcont);
//return $filcont;
$IterateRegion = ReadFileIterateRegion($filcont,$placehoder);
 continue;
}
return $filcont;
}

//function to get the number of open tag seen withen a string
function GetCloseTag($markup,$startpos = 0,$tagname = "ep-widget"){
    
    $openseen = 1; //the open tag seen is one at default, one is seen (the main open tag which the close tag is to be gotten)
    $closeseen = 0;$entagpos;$mainclose = 0;
  do{
    $entagpos = strpos($markup,'</'.$tagname.'>',$startpos);
    if($entagpos === false)break; //if no close tag found get out of the loop
    $mainclose = $entagpos; //update the close tag pos
    $closeseen++; //increament the total close seen
    //get the open tags between the last open tag and current close tag
    $alltag  = substr_count($markup,"<".$tagname,$startpos+1,$entagpos - $startpos);
    $openseen += $alltag; //add tags seen to total open tag seen
    $startpos = $entagpos + 2 + strlen($tagname); //locate and reset where the next close tag search will start from
  }while($openseen != $closeseen);

    
    /*while($openseen != $closeseen){ //while the open tag clossing not seen
       // $closeseen =  $closeseen == 0?1: $closeseen;
       // $openseen = $openseen==0?1:$openseen; //set the first open tagseen
       $closeseen++; //increament close seen, cause for every loop entarnce one close has been seen
        //get all open tag between
        $alltag  = substr_count($markup,"<".$tagname,$tagsStartPos+1,$entagpos - $tagsStartPos);
        $openseen += $alltag; //add to total open tag seen
       
        //return array($alltag,1,$mainclose);
        //set new positions
        $tagsStartPos = $entagpos;
        $entagpos = strpos($markup,'</'.$tagname.'>',$entagpos+1); //get the next close tag (incose the real closing tag is not gotten)
        if($entagpos !== false){
            $mainclose = $entagpos;
        }else{
            break;
        }
    }*/

    return $mainclose;
}

//dump data
function Populate($dataarr,$filcont=""){
    
    if(count($dataarr) > 0){ //if dynamic content is sent
        foreach($dataarr as $key=>$val){ //loop through all the Dynamic Content and insert accordinly
            //if($key != "Src" && $key != "DataSet"){
                if(is_array($val) || is_object($val)){
                //proccess the array
                //$ValueArr=array(),$Markup="",$placehoder="",$ParentPlaceholder=""
                
                $filcont = ReadFileProccessArrayValue($val,$filcont,$key);
                //Message("Is Array");
                
                }else{ //if value is not an array
                    
                    $filcont = ReadFileInsertValue($filcont,$key,$val);
                   

               // $filcont = str_replace('{{'.$key.'}}',$val,$filcont);
                }
           // }
        }
        }
        return $filcont;
}

function GetAttributeValue($str){
    $attrval = array();
    $tokenkey = "";
    $tokenval = "";
    $procspecialchar = true;
    $strvalind = 'key';
    if(trim($str) == "")return [];
    //loop through all character of the string
    $strlen = strlen( $str );
    for( $i = 0; $i <= $strlen; $i++ ) {
        $char = substr( $str, $i, 1 );
        if($char == "=" && $procspecialchar){ //if equal found and special character are allowed for proccing
            $strvalind = 'value'; //set current token reading to value
        }else if($char == '"' && $procspecialchar && $strvalind == 'value'){ //if token reading is value and value open quote found and symbol processing is allowed
            $procspecialchar = false; //disable symbol processing
        }else if($char == '"' && $procspecialchar == false && $strvalind == 'value'){  //if closing value qoute, indicate value reading end
            $procspecialchar = true; //disable symbol processing
            $strvalind = 'key'; //set token reading back to key
            //set the array
            $attrval[trim($tokenkey)] = $tokenval;
            //clear all tokens
            $tokenkey = "";
            $tokenval = "";
        }else{
            
                if($char == " " && $procspecialchar)continue;
                //if forming key
                if($strvalind == 'key'){
                    $tokenkey .= $char;
                }else{
                    $tokenval .= $char;
                }
            
            
        }
        
    }
    return $attrval;
}

//function to get the position of a character not withen an attribute value ("")
function GetCharPos($cchar,$mainstr,$start = 0){
    
    $totchar = strlen($mainstr);
    
    if($totchar < 1)return -1;
    $checkable = true; $valopen = false;$end = false;$ind = $start;
    while($ind < $totchar){
        $char = substr($mainstr,$ind,1);
        if($char == '"'){ //if value qoute found and not excaped
            //check if escaped
            if($ind > 0 && substr($mainstr,$ind - 1,1) == '\\'){
                //return "escaped - ".$ind;
                $ind = $ind + 1;
                continue;
                //escaped
            }else{ //if not excaped
                //toggle checkable
                $checkable = !$checkable;
            }
            if($checkable){ //if not withen value qoute
                $ind = $ind + 1;
                continue;
            }else{
                //check the clossing qoute
                $clsind = strpos($mainstr,'"',$ind + 1);
                //return $clsind;
                if($clsind === FALSE)return -1;
                $ind = $clsind;
            }
        }else{
            if($checkable){ 
              if($char == $cchar)return $ind;
              $ind++;
            }else{
                $clsind = strpos($mainstr,'"',$ind + 1);
                if($clsind === FALSE)return -1;
                $ind = $clsind;
            }
        }
    }
    return -1;
}

//process all widget set in the supplied markup
function GetGroupByName($markup,$objname = "ep-widget",$closebyName = false){
    global $baseurl;
    
    $widgetseen = array();
   $startIndex = 0;
   $end = false;
  
  while($end == false){
   //get and add section
   $openIndex = strpos($markup,"<".$objname,$startIndex);
   if($openIndex !== false){
       //get the open tag close chars
       //$openCloseIndex = strpos($markup,">",$openIndex+1+strlen($objname));
       $openCloseIndex = GetCharPos(">",$markup,$openIndex+1+strlen($objname));
      // if($openCloseIndex !== false){ //if valid
        if($openCloseIndex > -1){ //if valid
              //get the section name
              $namelen = $openCloseIndex-($openIndex + (1+strlen($objname)));
              //if($namelen > 0){
                  $WidgetName = trim(substr($markup,$openIndex+1+strlen($objname),$namelen));
                  
              //}else{
              //  $WidgetName = ""; 
             // }
              
              //get the entire opening string
              $WidgetOpening = substr($markup,$openIndex,($openCloseIndex + 1) - $openIndex);
             // $WidgetOpening = $markup;
              //look for the main closing tag
             // $closetag = $closebyName && $WidgetName != ""?'</'.$WidgetName.'>':'</'.$objname.'>';
              
              //Handle nexted tags (identify the closing tag even if same tag is nexted in it)
              if(!($closebyName && $WidgetName != "")){ //if the tag closing is the tag itself
                $closetag = '</'.$objname.'>';
               // GetCloseTag($markup,$startpos = 0,$tagname = "aim-widget")
                $mainclose = GetCloseTag($markup,$openCloseIndex+1,$objname);
                //$mainclose = strpos($markup,$closetag,$openCloseIndex+1);
              }else{
                  $closetag = '</'.$WidgetName.'>';
                $mainclose = strpos($markup,$closetag,$openCloseIndex+1);
              }
              
              $internalMarkup = "";
              if($mainclose !== false){//if the main closing found
                $internalMarkup = substr($markup,$openCloseIndex+1,$mainclose - ($openCloseIndex+1));
                $startIndex = $mainclose + strlen($closetag); //where to start the next search from
              }else{
                $closetag = "";
               $internalMarkup = substr($markup,$openCloseIndex+1); //take the rest 
               $end = true;
              }
              $rtninternalMarkup = $internalMarkup;
              //check if internalMarkup is url
              $tartchar = substr(trim($internalMarkup),0,1);
              //check if start with @ symbol
              if($tartchar == "@"){
                 //get the remaining part
                 $urlstr = substr(trim($internalMarkup),1);
                 //resolve the url
                 $urlstr = $baseurl.$urlstr;
                 //try to get the file
                 $filecont = file_get_contents($urlstr);
                 if($filecont){
                    $internalMarkup =  $filecont ;
                 }
              }

              //get the widget atributes
              //$WidgetName = trim($WidgetName);
              //if($WidgetName == "")continue;
              //Process the name to get the atrribute value part
              $wnamePart = explode(" ",$WidgetName);
              $attrpart = [];
              if(count($wnamePart) > 1){
                 $WidgetName  = array_shift($wnamePart); 
                // $attrpart = implode(" ",$wnamePart);
              }
              //populaye or user set attribut and value
              $wnamePart = implode(" ",$wnamePart);
              $attrpart = GetAttributeValue($wnamePart);

              $rsta = array("Name"=>$WidgetName,"Markup"=>$internalMarkup,"OpenTag"=>$WidgetOpening,"CloseTag"=>$closetag,"RawMarkup"=>$rtninternalMarkup,"Attribute"=>$attrpart);
              //if($WidgetName == ""){
                $widgetseen[] = $rsta;
             // }else{
               // $widgetseen[$WidgetName] = $rsta;
              //}
       }else{
           $end = true;
       }
   }else{ //if no section in markup
       $end = true;
   }
}
return $widgetseen;
}

?>