<?php

//donothing
//#R000
function DoNothing($Param){
    return [];
}

//Get all School Basic Details
function GetSchoolDetails($Param){
   global $dbo;
   //Get the school details
    $schooldet = $dbo->RunQuery("SELECT s.Name, p.colorScheme as ColorScheme, s.description as Description, s.ID as SID, s.AppThemeColor, p.wallpapers, s.FooterNote, s.email as Email, s.Phone, p.walldelay as WallDelay, s.Abbr as Abbreviation, SUBSTRING_INDEX(SUBSTRING_INDEX(p.colorScheme, ';', 1), ';', -1) as BaseColor, SUBSTRING_INDEX(SUBSTRING_INDEX(p.colorScheme, ';', 2), ';', -1) as ForeColor, CONCAT('Files/',s.logo) as Logo FROM school_tb s, portal_tb p");
    if(!is_array($schooldet))Error(4,": School Details");
    $schooldet = $schooldet[0]->fetch_assoc();

    //get the set wallpapers
    $setwp = trim($schooldet['wallpapers']);
    $forcolorarr = explode(",",$schooldet['ForeColor']);
    $LightColor = [];
    foreach($forcolorarr as $col){
$col = (int)$col;
$inc = 50;
$col = ($col + $inc) > 255?255:($col + $inc);
$LightColor[] = $col;
    }
    $schooldet["LightForeColor"] = implode(",",$LightColor);
    $schooldet["Wallpapers"] = [];
    //if no wall paper set
    if($setwp != ""){
        $setwpcond = "ID = ".str_replace("~"," OR ID = ",$setwp);
        //get all set wallpaper details
        //Get The School Wallpapers
        $schwp = $dbo->RunQuery("SELECT ID as WID, CONCAT('Files/UserImages/wallpapers/bgs/',wallpaper) as WallImage, wallheader as WallTitle, wallText as WallContent FROM wallpapers_tb WHERE $setwpcond");
        if(!is_array($schwp))Error(4," : Wallpapers");
        $schooldet["Wallpapers"] = $dbo->FetchAll($schwp[0],MYSQLI_ASSOC);
       // $schooldet["ss"] = "SELECT ID as WID, CONCAT('epconfig/UserImages/wallpapers/bgs/',wallpaper) as WallImage, wallheader as WallTitle, wallText as WallContent FROM wallpapers_tb WHERE $setwpcond";
    }

    

    return $schooldet;
  
}

//Get student details R002
function GetStudentDetails($Param){
    //sleep(4);
    
    session_start();
    /* if(!isset($Param['LoginName']) || trim($Param['LoginName']) == ""){
          if(isset($_SESSION['LoginName']) && trim($_SESSION['LoginName']) != ""){
            $Param['LoginName'] = $_SESSION['LoginName'];
          }else{
            Error(5);
          }
    } */
    HasLogin($Param);
    global $dbo;
    //global $Config;
    $LoginName = $dbo->SqlSafe($Param['LoginName']);
    
    $studdet = $dbo->RunQuery("SELECT s.SurName, s.FirstName, s.OtherNames, IF(s.RegNo='',s.JambNo,s.RegNo) as RegNo, s.id, s.Passport, s.Email, s.Phone, f.FacName, p.ProgName, s.OtherDet FROM studentinfo_tb s, fac_tb f, dept_tb d, programme_tb p WHERE s.ProgID = p.ProgID AND p.DeptID = d.DeptID AND d.FacID = f.FacID AND ( s.RegNo = '$LoginName' OR s.JambNo = '$LoginName')");
    if(!is_array($studdet))Error(4,": Reading Student Details Failed");
    if($studdet[1] < 1)Error(6,": ".$LoginName);
    $studdet = $studdet[0]->fetch_assoc();
    $_SESSION['LID'] = $studdet['id'];
    $_SESSION['LRegNo'] = $studdet['RegNo'];
    $studdet["DegreeName"] = "--";
    if(trim($studdet['OtherDet']) != ""){
        $odet = json_decode($studdet['OtherDet'],true);
        //remove data that are not neccessary
       foreach(["PayRef","PayID"] as $unes){
        if(isset($odet[$unes]))unset($odet[$unes]);
       }
        if(!is_null($odet)){
            $studdet = array_merge($studdet,$odet);
            //get the degree details
            if(isset($studdet['Degree'])){
                $degdet = $dbo->SelectFirstRow("school_degrees_tb","","ID=".$studdet['Degree']);
                if(is_array($degdet)){
                    $studdet["DegreeName"] = $degdet['Name'];
                }else{
                    $studdet["DegreeName"] = "--";
                }
            }
        }
       
    }
    //reprocess image url
    $passp = "logo.png";
    if(trim($studdet['Passport']) != ""){
        $passp = $studdet['Passport'];
        $passparr = explode("?",$passp);
        $passp = $passparr[0];
        $passparra = explode("/",$passp);
        if($passparra[0] == ".."){
            $passparra[0] = "";
        }else if($passparra[0] == "UserImages"){
           array_unshift($passparra,'Files');
        }

        $passp = ResolveFilePath(implode("/",$passparra));
        
    }
    
    // $studdet['Image'] = $dbo->ImageToDataURI()
    if(file_exists("../../../../".$dbo->Config["SubDir"].$passp)){
$studdet['DataUrIImage'] = $passp != ""?$dbo->ImageToDataURI("../../../../".$dbo->Config["SubDir"].$passp):"";
    $studdet['Image'] = $passp;
    }else{
        $studdet['DataUrIImage'] = $dbo->ImageToDataURI("../../images/bbwa/logo.png");
        $studdet['Image'] = $dbo->Config["Core"]."images/bbwa/logo.png";
    }
    //Error("CE",json_encode($studdet));
    //$studdet['ff'] = "../../../../".$Config["SubDir"].$passp;
    return $studdet;
    

}

//verify user password
function CheckPassword($Param){
    //Error(7);
    session_start();
    if(!isset($Param['LRegNo']))Error(8);
    if(!isset($Param['AccessCode']) || trim($Param['AccessCode']) == "")Error(5);
    global $dbo;
    $AccessCode = $dbo->SqlSafe($Param['AccessCode']);
    $RegNo = $dbo->SqlSafe($Param['LRegNo']);
    $passw = $dbo->RunQuery("SELECT JambNo FROM accesscode_tb WHERE JambNo = '{$_SESSION['LRegNo']}'AND AccessCode = '$AccessCode'");
    if(!is_array($passw))Error(4,": Authenticating Access Code Failed.");
    if($passw[1] < 1)Error(7);
    $passw = $passw[0]->fetch_assoc();
    $_SESSION['ALID'] = $_SESSION['LID'];
    $_SESSION['ALRegNo'] = $Param['LRegNo'];
    $_SESSION['LoginName'] = $Param['LRegNo'];
    return $passw;
}

//get all application R004
function GetApplications($Param){
  global $dbo;
  $cnd = "";
  //Error(9,json_encode($Param));
  //check ApplyGID is sent
  if(isset($Param['ApplyGID']) && trim($Param['ApplyGID']) != ""){
      $appgidarr = explode("_",$Param['ApplyGID']);
      if(count($appgidarr) > 0){
          $cnd = " AND (ID=".implode(" OR ID=",$appgidarr).") AND Enable=1";
      }
      //$cnd = (int)$Param['ApplyGID'] > 0?" AND ID=".$Param['ApplyGID']:"";
  }
  //Error(4," - ".$Param['ApplyGID']);
  //check Scope is sent
  if(isset($Param['Scope']) && trim($Param['Scope']) != ""){
    $cnd .= " AND (Scope = '{$Param['Scope']}' OR Scope = 'ALL')";
  }
  
  //get all the group
  $appGroup = $dbo->Select("new_apply_group_tb","*, IF(Enable=1,'Enabled','Disabled') as Status","ID >= 1".$cnd . " ORDER BY MenuOrder");
  if(!is_array($appGroup))Error(4,": Reading Application Failed.");
  if($appGroup[1] < 1)Error(9," : Application Not Available or Disabled");
  $applygrparr = [];
  $JointID = "";
  $firstLogo = "";
  while($ind = $appGroup[0]->fetch_assoc()){
      $applygrpid = $ind["ID"];
      $JointID .= "_".$applygrpid;
      if($firstLogo == "")$firstLogo = trim($ind["Logo"]);
      //get all apply details
      $app = $dbo->Select("new_apply_tb","ID as AID, Name as AppName, Descr as AppDescr, Logo as AppLogo, Placeholder","Enable=1 AND GroupID=".$applygrpid." ORDER BY MenuOrder");
      if(!is_array($app)){
        $ind["Applications"] = InternalError(4);
      }else{
        $ind["Applications"] = $dbo->FetchAll($app[0],MYSQLI_ASSOC);
        
      }
      $applygrparr[] = $ind;
      
      // $schooldet["Wallpapers"] = $dbo->FetchAll($schwp[0],MYSQLI_ASSOC);

  }
  return ["AppGroup"=>$applygrparr,"PAGEID"=>ltrim($JointID,"_"),"Logo"=>$firstLogo];
}


//function to get all Page element by Application ID and The Page Number - R005
function GetPageElements($Param){
   session_start();
  
   //return $Param;
    global $dbo; global $Request;
    if(!isset($Param['ApplyID']) || (int)$Param['ApplyID'] == 0)Error(10);
    //get application details
    $ApplyDet = $dbo->SelectFirstRow("new_apply_tb",'',"ID=".$dbo->SqlSafe($Param['ApplyID']),MYSQLI_ASSOC);
    if(!is_array($ApplyDet))Error(10);
    if($ApplyDet['Status'] == "CLOSED")Error(22," for ".$ApplyDet['Name']);
    //Check if payment must be made
    $PayID = (int)$ApplyDet['PayID'];
    if($PayID > 0){ //if payment must be made befor access is given
        //get the payment details
        
        if(!isset($Param['LoginName']))Error(8," : This Features requires payment, kindly login and try again");
        $paydet = $dbo->SelectFirstRow("item_tb","ItemName","ID=$PayID");
        if(!is_array($paydet))Error(14, ": Report this Error to the Tech Unit");
        $bases = (int)$ApplyDet['PayBases'];
        $stdlvlsemdet = GetStudentCurrentLevelSemester($Param);
        $studlvl = $stdlvlsemdet['LevelID'];
        $studsem = $stdlvlsemdet['SemID'];
        //get the student programme id
        $studProg = $dbo->SelectFirstRow("studentinfo_tb","ProgID","RegNo='".$dbo->SqlSafe($Param['LoginName'])."' OR JambNo='".$dbo->SqlSafe($Param['LoginName'])."'");
        if(!is_array($studProg))Error(8," : This Features requires payment, kindly login and try again");
        $StudProgID = $studProg['ProgID'];
        $basescond = "AND Lvl=$studlvl AND Sem=$studsem";
        if($bases == 2){//level bases
            $basescond = "AND Lvl=$studlvl";
        }else if($bases > 2){ //entire academic programme bases
            $basescond = "";
        }
        //confirm if payment made
        $paymaderst = $dbo->SelectFirstRow("payhistory_tb","ProgID","RegNo='".$dbo->SqlSafe($Param['LoginName'])."' $basescond AND ProgID=$StudProgID ORDER BY SemPart DESC LIMIT 1");
        if(!is_array($paymaderst))Error(13," (".$paydet['ItemName'].")");
        
    }
    $Pages =  (!is_null($ApplyDet['Pages']) && trim($ApplyDet['Pages']) != "")?json_decode($ApplyDet['Pages'],true):[];
    $isext = "";
    if(is_null($Pages)){ //assuming it is a url
        //check if it is a valid url
        if (filter_var($ApplyDet['Pages'], FILTER_VALIDATE_URL)) {
          $ApplyDet['Dir'] = "General/External";
          $isext = trim($ApplyDet['Pages']);
        }else{
          $Pages = [];
          //Error(16,": Is Not Url - ".$ApplyDet['Pages']);
        }
      }
    $PageControl =  !is_null($ApplyDet['PageControl'])?json_decode($ApplyDet['PageControl'],true):[];

    $ApplyDetRetn = ["ApplyName"=>$ApplyDet['Name'],"ApplyDescr"=>$ApplyDet['Descr'],"ApplyLogo"=>$ApplyDet["Logo"],"ApplyGroupID"=>$ApplyDet["GroupID"],"ApplyColor"=>$ApplyDet["Color"],"Dir"=>$ApplyDet['Dir']];

   
    
    //get the global data set
    $GlobalData = [];
    if(!is_null($ApplyDet["GlobalData"]))$GlobalData = json_decode($ApplyDet["GlobalData"],true);
    if(is_null($GlobalData))$GlobalData = [];
    if(trim($isext) != ""){
        $GlobalData['ExtUrl'] = $isext;
    }
    $cond = "";
    
    if(isset($Param['PageNum']) && (int)$Param['PageNum'] > 0){
        $PageNumDir = (int)$Param['PageNum'];
        $NextPageNumDir = $PageNumDir + 1;
        if(count($Pages) > 0){//if pages set
           //check if the supplied page not exist
           $pagekey = array_search($Param['PageNum'],$Pages);
           if($pagekey === FALSE){
            $PageNumDir = $Pages[0];
            $NextPageNumDir = $Pages[1];
           }else{
               //get the next page from the pages array, if no more next use the first(return to the first)
            $NextPageNumDir = isset($Pages[$pagekey + 1])?$Pages[$pagekey + 1]:$Pages[0];
           }
        }
        $cond = "AND PageNumber = ".$dbo->SqlSafe($PageNumDir);
    }else if(count($Pages) > 0){
        $PageNumDir = $Pages[0];
        $NextPageNumDir = $Pages[1];
    }else{
        $PageNumDir = 1; //default pagenum value for dir page type
        $NextPageNumDir = 2;
    }

    $Param['PageNum'] = $PageNumDir;
    //Error(0," - ".$PageNumDir);

    //process page control settings
    if(isset($PageControl[$PageNumDir])){
        foreach($PageControl[$PageNumDir] as $PCID => $status){
            $PageControl[$PageNumDir][$PCID] = $status?[1]:[];
        }
    }

    $pageDet = ["ApplyID"=>$Param['ApplyID'],"ApplyGroupID"=>$ApplyDet["GroupID"]];
    //check if file type
    if(!is_null($ApplyDet['Dir'])){
        //
       //get the PageDetails
        //check if file exixt
        //first check in school directory incase general page is overwritten
        $lookup = "../../Pages/";
        if(file_exists("../../../../".$dbo->Config["SubDir"]."Pages/".$ApplyDet['Dir']."/".$PageNumDir.".json")){
            
            $lookup = "../../../../".$dbo->Config["SubDir"]."Pages/";
        }
        
        if(file_exists($lookup.$ApplyDet['Dir']."/".$PageNumDir.".json")){
           
            $locate = $lookup.$ApplyDet['Dir']."/".$PageNumDir.".json";
            $locatekey = str_replace(array("/","."),"_",$locate);
            //check if cached
            if(isset($_SESSION[$locatekey]) && trim($_SESSION[$locatekey]) != ""){
                
                $pagejsondet = $_SESSION[$locatekey];
            }else{
                $pagejsondet = file_get_contents($locate);
                
            }
            
           // Error(0,": ".$pagejsondet);
            if($pagejsondet !== FALSE && trim($pagejsondet) != ""){
                $jsonobj = json_decode($pagejsondet,true);
                if(!is_null($jsonobj)){ //if valid
                  $page = $jsonobj[0];
                  //form page det
                  $pageDet['Name'] = isset($page['name'])?$page['name']:"";
                  $pageDet['Logo'] = isset($page['logo'])?$page['logo']:"";
                  $pageDet['Descr'] = isset($page['data'])?$page['data']:"";
                  $pageDet['PageMarkup'] = $pagejsondet;
                  $pageDet['PreRID'] = isset($page['request']) && isset($page['request']['pre'])?$page['request']['pre']:"";
                  $pageDet['SubmitRID'] = isset($page['request']) && isset($page['request']['post'])?$page['request']['post']:"";
                  $pageDet['PreRequestData'] = isset($page['request']) && isset($page['request']['data'])?json_encode($page['request']['data']):"";
                }
            }
        }
    }

    // if(count($pageDet) < 1){
        if(!isset($pageDet['PageMarkup'])){
        $pageDet = $dbo->SelectFirstRow("new_apply_page_tb",'',"ApplyID=".$dbo->SqlSafe($Param['ApplyID'])." ".$cond,MYSQLI_ASSOC);
    if(!is_array($pageDet))Error(16); 
    }
    
    
    
   // $AllRst['R005'] = $pageDet;
    //get the pre request ID
    $preRID = $pageDet['PreRID'];
    $preRdata = $pageDet['PreRequestData'];
    //$preRdata['NextPageNum'] = $NextPageNumDir;
    $pageDet['NextPageNum'] = $NextPageNumDir;
    $pageDet['NowPageNum'] = $PageNumDir;
    
    if(trim($preRID) != ""){
        
        $preRdata = trim($preRdata) != ""?json_decode($preRdata,true):[];
        if(isset($PageControl[$PageNumDir]))$preRdata = array_merge($preRdata,$PageControl[$PageNumDir]);
        $preRdata['NextPageNum'] = $NextPageNumDir;
        $preRdata['NowPageNum'] = $PageNumDir;
        $preRdata = array_merge($preRdata,$Param,$GlobalData);
        $RIds = explode(",",$preRID);
        //$preRdata = array_merge($preRdata,$Param);
        /* $RIds = explode(",",$preRID);
        $preRdata = array_merge($preRdata,$Param,$RIds,$GlobalData); */
        /* $RIds = explode(",",$preRID);
        $preRdata = array_merge($preRdata,$Param); */
        
        foreach ($RIds as $IndRid) {
            //check if function exist
            if(!function_exists($Request[$IndRid]))Error(3," : ".$IndRid);
            
            //call the script
            $rst = call_user_func($Request[$IndRid],$preRdata);
            //check if PagNum is changed from pre script
            if(isset($rst['PageNum']) && (int)$rst['PageNum'] != (int)$PageNumDir){

                return GetPageElements(array_merge($Param,$rst));
            }
           
            $preRdata = array_merge($preRdata,$rst);
            //Error(10,': '.$rst);
            $pageDet = array_merge($pageDet,[$IndRid=>$rst]);
        }

        //check if current PageNum has changed

    }
    
    $pageDet = array_merge($pageDet,$_SESSION);
    //Error(10,': '.json_encode($PageControl[$PageNumDir]));
    if(isset($PageControl[$PageNumDir]))$pageDet = array_merge($pageDet,$PageControl[$PageNumDir]);
    //
    //Error(16,json_encode($GlobalData)); 
    return array_merge($pageDet,$Param,$ApplyDetRetn,$GlobalData);
}

//get the payment type - R006
function GetPaymentTypes($Param){
    global $dbo;
    $PayIDCond = (isset($Param['PayID']) && (int)$Param['PayID'] > 0)?"ID=".$Param['PayID']:"1=1";
    //return $Param['PayID'];
    $paydet = $dbo->Select("item_tb","ID as PayID, ItemName as PayName, ItemDescr as PayDescr",$PayIDCond);
      if(!is_array($paydet)){
        Error(4);
      }else{
        return $dbo->FetchAll($paydet[0],MYSQLI_ASSOC);
      }
}


//R028
//get the current payment type for a student
function GetAllPaymentTypes($Param){
    session_start();
    Error(4);
    global $dbo;    
    //get all payment types for student (except application payments)
    $payIds = $dbo->Select("item_tb","ID,ItemName","studType='r'");
    
    if(is_array($payIds) && $payIds[1] > 0){
        
      $itemdetails = [];
      $cnt = 0;
      while($paydet = $payIds[0]->fetch_assoc()){
        $PayAmount = $pstatus = [];
        $Param["PayID"] = $paydet['ID'];
        //check if student has paid
        //$payst = $dbo->SelectFirstRow("pay")
           //get payamount
           $PayAmount = GetPaymentAmt($Param);
           if((float)$PayAmount['Amount'] <= 0)continue; //if amount is zero, meaning it is not a valid payment
           if(!isset($Param['StudentDetails']))$Param['StudentDetails'] = $PayAmount['StudentDetails'];
           $cnt++;
           //if($cnt == 3){
               $Param['cnt'] = $cnt;
                $pstatus = CheckPayStatus($Param);
                
          // }
          
           $itemdetails[] = array_merge($PayAmount,$paydet,$pstatus);
          
           
      }
      
      return $itemdetails;
    }else{
        Error(4);
    }
} 

//Internal
if(!function_exists('HighestSemester')){
    function HighestSemester(){
        global $dbo;
    //get highest semester
    $highsem = 0;
    $higestsem = $dbo->SelectFirstRow("semester_tb","ID,IF(Num=0,ID,Num) as Num","Enable = 1 ORDER BY Num DESC, ID DESC LIMIT 1");
    if(!is_array($higestsem)){
        /* $higestsem['Num'] = $higestsem['Num'] == 0?$higestsem['ID']:$higestsem['Num'];
    }else{ */
        $higestsem = ["ID"=>2,"Num"=>2,"Sem"=>"Second","Descr"=>"Second Semester"]; 
    }
    return $higestsem;
    }
}


//R031
//get the current payment type for a student
function GetAllPaymentTypes2($Param){
    
   // sleep(4);
  if(!isset($Param['LoginName']) || trim($Param['LoginName']) == "")Error(8);
  $extrystr = '';
  //level cache
  $levelCache = [];
  //level cache
  $semesterCache = [];
    session_start();
    global $dbo;   
    //get the student programme details 
   /* $progdet = $dbo->SelectFirstRow("studentinfo_tb s, programme_tb p","s.RegNo,s.JambNo,p.YearOfStudy","(s.RegNo = '{$Param['LoginName']}' || s.JambNo = '{$Param['LoginName']}') && s.ProgID = p.ProgID");
     $studdet =  $Param['StudentDetails'];
   }else{*/
    $progdet = GetBasicInfo($Param['LoginName'], "", "a", 1,MYSQLI_ASSOC); 
    if(!is_array($progdet))Error(8);

    $Param['ProgID'] = $progdet['ProgID'];
    $Param['StudentDetails'] = $progdet;

    $Param['LoginName'] = (is_null($progdet['RegNo']) || trim($progdet['RegNo']) == "")?$progdet['JambNo']:$progdet['RegNo'];

    $yearst = (int)$progdet['YearOfStudy']; //the student year of Study
    //get all payment types for student (except application payments)
    $payIds = $dbo->Select("item_tb","*,ID as PayID, ItemName as PayName, ItemDescr as PayDescr, PayBrkDn as BreakDown","studType='r'",MYSQLI_ASSOC);
    
    if(is_array($payIds) && $payIds[1] > 0){
           
      $itemdetails = [];
      $cnt = 0;
      $highsemarr = HighestSemester();
      
      while($paydet = $payIds[0]->fetch_assoc()){
        $PayAmount = $pstatus = [];
        $Param["PayID"] = $paydet['ID'];
        $Param["PayDetails"] = $paydet; //to be use in functions, not need to get it again
      
        //get the payment control details
        $paysetting = $dbo->SelectFirstRow($paydet['ControlTable'],"","ID=".$paydet['ControlTableID']." LIMIT 1");
        
        if(!is_array($paysetting)){ continue;} //if no setting found ignore
        
        //check status
        if($paysetting['Status'] == "CLOSED")continue;
        if($paysetting['PartPay'] == "FALSE")$paysetting['PartPayShare'] = "FULL";
        
        
        //get highest payment
        $higestPay = GetHighestPayment($Param);
        $higestPay['HighestSemesterNumber'] = $highsemarr['Num']; //the highest semster num in the school
        
        //merge the control details for details data for GetNextLSS
        $higestPay = array_merge($higestPay,$paysetting);
        
        //if no payment found, use the school start lvl and sem of the student to determine his/her last payment
        if(isset($higestPay['Error'])){//no payment found
            
            list($studschstartlvl,$studschstartsem) = GetStudentLevelSemesterWhenSchoolStart($Param['LoginName']);
            $studschstartsem = $studschstartsem - 1; //take back so that GetNextLSS will take it to the start level
            if($studschstartsem < 1){ //if lower level
               // if($studschstartlvl > 1){
                    $studschstartlvl = $studschstartlvl - 1;
                    $studschstartsem = $higestPay['HighestSemesterNumber'];
               // }else{

               // }
            }
            $startpay = ["LevelID"=>$studschstartlvl,"SemesterID"=>$studschstartsem,"SemesterNum"=>$studschstartsem,"SemesterPartID"=>3];
            $higestPay = array_merge($higestPay,$startpay);
            //Error(8,": ".json_encode($startpay));
            //get the next LSS
           $NLSS = GetNextLSS($higestPay);
           
        }else{ //if last payment found
            
        //get the next LSS
        $NLSS = GetNextLSS($higestPay);
        //Include the last payment in the front of the array, to int the student of his/her last payment
        array_unshift($NLSS,["LevelID"=>$higestPay['LevelID'],"SemesterID"=>$higestPay['SemesterID'],"SemesterPartID"=>$higestPay['SemesterPartID'],"SemesterNum"=>$higestPay['SemesterNum']]);
        }
        
        

        //if($paydet['ID'] == 7)Error(8,json_encode($NLSS));
        
         //SemesterID represent the payment policy can be higher than the school highest semester (Full Session Payment)
         //Include the last payment in the front of the array, to int the student of his/her last payment
        /*  if(!isset($higestPay['Error'])){
            array_unshift($NLSS,["LevelID"=>$higestPay['LevelID'],"SemesterID"=>$higestPay['SemesterID'],"SemesterPartID"=>$higestPay['SemesterPartID'],"SemesterNum"=>$higestPay['SemesterNum']]);
         } */

         

/* if(!isset($Param['PayID']) || (int)$Param['PayID'] == 0)Error(11);
    if(!isset($Param['LevelID']) || (int)$Param['LevelID'] == 0)$Param['LevelID']=1;
    if(!isset($Param['SemesterID']) || (int)$Param['SemesterID'] == 0)$Param['SemesterID']=1;
    if(!isset($Param['SemesterPartID']) || (int)$Param['SemesterPartID'] == 0)$Param['SemesterPartID']=3;
    if(!isset($Param['PayDate']) || trim($Param['PayDate']) == "")$Param['PayDate']=NULL; */

        //check if student has paid
        //$payst = $dbo->SelectFirstRow("pay")
        foreach($NLSS as $LSS){
            $Param['LevelID'] = $LSS['LevelID'];
            $Param['SemesterID'] = $LSS['SemesterID'];
            $Param['SemesterPartID'] = $LSS['SemesterPartID'];
            $Param['SemesterNum'] = $LSS['SemesterNum'];
             //get level det
             
           //get payamount
           $PayAmount = GetPaymentAmt($Param);
           //Error(4," - ".$paydet['ID']." Amt-".$PayAmount['Amount']);
           if((float)$PayAmount['Amount'] <= 0)continue; //if amount is zero, meaning it is not a valid payment
           //help GetPaymentAmt to not try get student details again so far it has gotten it once
           if(!isset($Param['StudentDetails']))$Param['StudentDetails'] = $PayAmount['StudentDetails'];
           $studet = $PayAmount['StudentDetails'];//$yearst
           if((int)$Param['LevelID'] > $yearst){ //Extra Year
            //get the extrayear string
            if($extrystr == '')$extrystr = ExtraLevelString();
            //get the extrayear elapse
            $elapsyear = (int)$Param['LevelID'] - $yearst;
            $leveldet = ["LevelName"=>$extrystr." ".$elapsyear,"Level"=>$Param['LevelID']];
           }else{ //if valid level
            if(isset($studet['StudyID'])){
                //check if the level is ni cache already
               if(isset($levelCache[$Param['LevelID']])){
                $leveldet = $levelCache[$Param['LevelID']];
               }else{
                   //get level details
                        //get the student current Level details
            $leveldet = $dbo->SelectFirstRow("schoollevel_tb","*, ID as LID, IF(Descr='',Name,Descr) as LevelName","Level={$Param['LevelID']} AND StudyID=".$studet['StudyID'],MYSQLI_ASSOC);
            $levelCache[$Param['LevelID']] = $leveldet;
               }
                        
            //if the level doeas not exist
            
                    }else{
                        $leveldet = ["LevelName"=>$Param['LevelID'],"Level"=>$Param['LevelID']];
                    }
           }
        
    if($Param['SemesterID'] > $highsemarr['Num']){
        $semdet = ["SemName"=>"Full Session","SemID"=>$highsemarr['Num'] + 1];
    }else{
        if(isset($semesterCache[$Param['SemesterID']])){
            $semdet =  $semesterCache[$Param['SemesterID']];
        }else{
          //get the student semester det
    $semdet = $dbo->SelectFirstRow("semester_tb","*, IF(Num=0,ID,Num) as SemID, Descr as SemName","(Num > 0 && Num={$Param['SemesterID']}) || ID={$Param['SemesterID']} ORDER BY Num DESC",MYSQLI_ASSOC);
    $semesterCache[$Param['SemesterID']] = $semdet;
        }

    }
    //if($Param["PayID"] == 7)Error(8, json_encode($semdet));
            
    if($Param['SemesterPartID'] == 1){
        $semdet["SemPartName"] = "PART";
    }else if($Param['SemesterPartID'] == 2){
        $semdet["SemPartName"] = "BALANCE";
    }else{
        $semdet["SemPartName"] = "FULL";
    }
    $semdet["SemPartID"] = $Param['SemesterPartID'];
    
    //if(!is_array($semdet))Error(31);
           $cnt++;
           //if($cnt == 3){
               $Param['cnt'] = $cnt;
               //disable deep verification
               $Param['Deep'] = false;
                $pstatus = CheckPayStatus($Param);
                
          // }
          if(trim($studet['RegNo']) == "")$studet['RegNo'] = $studet['JambNo'];
           $itemdetails[] = array_merge($PayAmount,$paydet,$pstatus,$leveldet,$semdet,["RegNo"=>$studet['RegNo']]);
        }
           
          
           
      }
      
      return $itemdetails;
    }else{
        Error(4);
    }
}

//get the student Highest Payment
//R032
function GetHighestPayment($Param){
    //Level Based - will still work on Ses and Manual Based
    session_start();
    global $dbo;
    if(!isset($Param['LoginName']) || trim($Param['LoginName']) == ""){
        //Error(5); 
          if(isset($_SESSION['LoginName']) && trim($_SESSION['LoginName']) != ""){
            $Param['LoginName'] = $_SESSION['LoginName'];
          }else{
           // Error(5);
          }
    }

      if(isset($Param['LoginName']) && trim($Param['LoginName']) != ""){
        //   $progID = GetStudentProgIDForPay($Param['LoginName']);
          $progID = $Param['ProgID'];
        //get the student higest Payment Record
           $highpay = $dbo->SelectFirstRow("payhistory_tb","*, Lvl as LevelID, Sem as SemesterID, SemPart as SemesterPartID, IF(SchSem=0,Sem,SchSem) as SemesterNum","RegNo='".$dbo->SqlSafe($Param['LoginName'])."' AND PayID=".$Param["PayID"]." AND ProgID=$progID ORDER BY Lvl DESC, Sem DESC, SemPart DESC LIMIT 1",MYSQLI_ASSOC);
            if(is_array($highpay)){
                return $highpay;
            }else{
                return ["Error"=>true];
            }
      }
}

//Get the next payment
function GetNextLSS($Param){

   $Lvl = isset($Param['LevelID'])?(int)$Param['LevelID']:1;
   $Sem = isset($Param['SemesterID'])?(int)$Param['SemesterID']:0; //0 represent unset
   $SemNum = isset($Param['SemesterNum'])?(int)$Param['SemesterNum']:1; //1 represent unset - First Semester
   $SemPart = isset($Param['SemesterPartID'])?(int)$Param['SemesterPartID']:0;
   $highsemnum  = isset($Param['HighestSemesterNumber'])?(int)$Param['HighestSemesterNumber']:0;
   if($highsemnum == 0){
      $hs = HighestSemester();
      $highsemnum = $hs['Num'];
   }
   $PartPay = isset($Param['PartPay'])?$Param['PartPay']:"FALSE";
   $Part = isset($Param['PartPayShare']) && $PartPay !== "FALSE"?$Param['PartPayShare']:"FULL"; //GET the school part payment share
    //GET the school part payment share

   //*************************************************************************** */
  //Note: This script handles payment on semester bases only, i.e full session payment not process (A new field is required in both order_tb and payhistory_tb to hold the Real Semster - 1 or 2, while the pay Sem - 1 or 2 or 3:payed all session)
  /****************************************************************************** */

   /****************************************************************************** */
     //determine if payment will allow full only, both, part only
    /****************************************************************************** */

     
       //$studLSS = GetStudentLevelSemester([]);
$NLSS = CalculateNextLSS($Lvl,$Sem,$SemNum,$SemPart,$Part,$highsemnum,$PartPay);

//get level 
$NLvl = $NLSS[0]["LevelID"];
if($Param['PartPayRestrict'] != "-1"){
    $partpresarr = explode("~",$Param['PartPayRestrict']);
    if(in_array($NLvl."",$partpresarr)){ //the derived level is restricted to be FULL Payment
        $NLSS = CalculateNextLSS($Lvl,$Sem,$SemNum,$SemPart,"FULL",$highsemnum);
    }
}

return $NLSS;
   
}

//Internal
function CalculateNextLSS($Lvl,$Sem,$SemNum,$SemPart,$Part,$highsemnum,$PartPay){
    $NLSS = [];
    //$FullRestrict = false;
    if($Part == "QUATER"){
        if($Sem == 0)$Sem=1;
        //if($SemPart == 0)$Sem=1;
        //increament sempart
          $SemPart++;
          if($SemPart > 2){
              $SemPart = 1;
              $Sem++;
              if($Sem > $highsemnum){
                  $Sem = 1;
                  $SemNum = 1;
                  $Lvl++;
              }
          }
          $NLSS[] = ["LevelID"=>$Lvl,"SemesterID"=>$Sem,"SemesterPartID"=>$SemPart,"SemesterNum"=>$SemNum];
          //if SemPart is 1 meanin new sem, include option of paying full
           if($SemPart == 1){
            $NLSS[] = ["LevelID"=>$Lvl,"SemesterID"=>$Sem,"SemesterPartID"=>3,"SemesterNum"=>$SemNum]; 
          } 
          if($Sem == 1 && $PartPay != "STRICT"){
            $NLSS[] = ["LevelID"=>$Lvl,"SemesterID"=>($highsemnum + 1),"SemesterPartID"=>3,"SemesterNum"=>$SemNum]; 
          }
          return $NLSS;
      }elseif($Part == "HALF"){
        //if($Sem == 0)$Sem=1;
          //check if last payment is QUATER
          if($SemPart == 1){
              return CalculateNextLSS($Lvl,$Sem,$SemNum,$SemPart,"QUATER",$highsemnum,$PartPay);
          }
          $SemPart = 3;
          $Sem++;
          if($Sem > $highsemnum){
            $Sem = 1;
            $SemNum = 1;
            $Lvl++;
        }
        $NLSS[] = ["LevelID"=>$Lvl,"SemesterID"=>$Sem,"SemesterPartID"=>$SemPart,"SemesterNum"=>$SemNum];
        if($Sem == 1 && $PartPay != "STRICT"){
            $NLSS[] = ["LevelID"=>$Lvl,"SemesterID"=>($highsemnum + 1),"SemesterPartID"=>3,"SemesterNum"=>$SemNum]; 
          }
        return $NLSS;
        
      }else{

          if($Sem == 1){
            return CalculateNextLSS($Lvl,$Sem,$SemNum,$SemPart,"HALF",$highsemnum,$PartPay); 
          }
          $SemPart = 3;
          $Sem = $highsemnum + 1;
          $SemNum = 1; //you can only make full payment once in a session and such payment will be expected to be paid in the first semester
         // if($SemNum > )
          $Lvl++;
          $NLSS[] = ["LevelID"=>$Lvl,"SemesterID"=>$Sem,"SemesterPartID"=>$SemPart,"SemesterNum"=>$SemNum,"kkk"=>$highsemnum];
          return $NLSS;
      }

      
}


//get payment amt - R007
function GetPaymentAmt($Param){
    session_start();
    global $dbo;
    if(!isset($Param['PayID']) || (int)$Param['PayID'] == 0)Error(11);
    if(!isset($Param['LevelID']) || (int)$Param['LevelID'] == 0)$Param['LevelID']=1;
    if(!isset($Param['SemesterID']) || (int)$Param['SemesterID'] == 0)$Param['SemesterID']=1;
    if(!isset($Param['SemesterNum']) || (int)$Param['SemesterNum'] == 0)$Param['SemesterNum']=1;
    if(!isset($Param['SemesterPartID']) || (int)$Param['SemesterPartID'] == 0)$Param['SemesterPartID']=3;
    if(!isset($Param['PayDate']) || trim($Param['PayDate']) == "")$Param['PayDate']=NULL;
    $studdet = [];
    if(!isset($Param['LoginName']) || trim($Param['LoginName']) == ""){
        //Error(5); 
          if(isset($_SESSION['LoginName']) && trim($_SESSION['LoginName']) != ""){
            $Param['LoginName'] = $_SESSION['LoginName'];
          }else{
            //Error(5);
          }
    }

          if(isset($Param['LoginName']) && trim($Param['LoginName']) != ""){

   // $studdet = $dbo->SelectFirstRow("studentinfo_tb","","RegNo='".$dbo->SqlSafe($Param['LoginName'])."' OR JambNo='".$dbo->SqlSafe($Param['LoginName'])."'",MYSQLI_ASSOC);
   if(isset($Param['StudentDetails']) && count($Param['StudentDetails']) > 0){
    $studdet =  $Param['StudentDetails'];
   }else{
       $studdet = GetBasicInfo($Param['LoginName'], "", "a", 1,MYSQLI_ASSOC);
       //    if(!is_array($studdet))Error(8);
   if(is_array($studdet)){
    if(trim($studdet['OtherDet']) != ""){
       $studdet = array_merge($studdet,json_decode($studdet['OtherDet'],true));
    }
       }else{ //if student details not exist remove from session
        unset($_SESSION['LoginName']);
       }
   }
   

          }

    //get the payment breakdown from db
    if(isset($Param["PayDetails"])){
        $paydet = $Param["PayDetails"];
    }else{
        $paydet = $dbo->SelectFirstRow("item_tb","ID as PayID, ItemName as PayName, ItemDescr as PayDescr, 	PayBrkDn as BreakDown","ID=".$Param['PayID']." LIMIT 1",MYSQLI_ASSOC);
    }
    
    if(!is_array($paydet))Error(4);
    $paybrd = PaymentBreakDown($paydet['BreakDown'],$Param['LevelID'],$Param['SemesterID'],$studdet,$Param['SemesterPartID']);
    if(!is_array($paybrd))Error(12);
    return ["Amount"=>$paybrd[0],"FAmount"=>$paybrd[1],"StudentDetails"=>$studdet,"PayDetails"=>$paydet];

}

//initialize payment - R008
function InitalizePayment($Param){
    //Error("CE",$Param['PayRef']);
    //Error(11);
    //return 'aaaa';
    session_start();
    global $dbo; global $__Root__; //global $Config;
    
    if(!isset($Param['PayRef']) || trim($Param['PayRef']) == ""){
        if(!isset($Param['PayID']) || (int)$Param['PayID'] == 0)Error(11,json_encode($Param));
      if(!isset($Param['LevelID']) || (int)$Param['LevelID'] == 0)$Param['LevelID']=NULL;
      if(!isset($Param['SemesterID']) || (int)$Param['SemesterID'] == 0)$Param['SemesterID']=NULL;
      if(!isset($Param['SemesterPartID']) || (int)$Param['SemesterPartID'] == 0)$Param['SemesterPartID']=3;
     // Error("CE",json_encode($Param));
//initialize payment
$RegNo = "";

//check if anonymous payee
if(isset($Param["RegNo"])){
    
  $RegNo = $Param["RegNo"];
}elseif (isset($Param["PayeeEmail"])){
 //anaonymous
 //check if exist already in payee_tb
 $payeedet = $dbo->SelectFirstRow("payee_tb","","PayeeID='".$Param["PayeeEmail"]."'");

 if(!is_array($payeedet)){
   
     //insert in payee_tb
     $jsotherdet = json_encode($Param);
    
        $insert = $dbo->Insert("payee_tb",array(
            "PayeeID"=>$Param["PayeeEmail"],
            "Name"=>$Param['PayeeFullName'],
            "Descr"=>$Param['PayeePhone'],
            "OtherDet"=>$jsotherdet
        ));
        //return $insert;
 }
 $RegNo = $Param["PayeeEmail"];
}elseif (isset($_SESSION["LRegNo"])) {
    $RegNo = $Param["LRegNo"];
}else{
    Error(1);
}

//!isset($RegNo) || !isset($Lvl) || !isset($Sem) || !isset($SemPart) || !isset($PayID)
if(is_null($Param['LevelID']) || is_null($Param['SemesterID'])){ //if no level set
//get the student current level
$curlvlsem = GetStudentCurrentLevelSemester(["LoginName"=>$RegNo]);
$Param['SemesterID'] = $curlvlsem['SemID'];
$Param['LevelID'] = $curlvlsem['LID'];
}
//run the initialization script
$data = ["RegNo"=>$RegNo,"Lvl"=>$Param['LevelID'],"Sem"=>$Param['SemesterID'],"SemPart"=>$Param['SemesterPartID'],"PayID"=>$Param['PayID'],"SubDir"=>urlencode($dbo->Config['SubDir'])];
if(isset($Param['Amt']))$data["Amt"] = $Param['Amt'];

//Error(12," : ".$__Root__);
$int = $dbo->Post($__Root__."general/Payment/init.php",$data);
//Error("CE",$int['Error']);
//Error(12," : No Valid Ref");
//return $int;
//check if error occur
if(isset($int['Error'])){
    if(trim($int['Error']) == "")$int['Error'] = "UNKNOWN ERROR";
    Error("CE",$int['Error']);
}
if(!isset($int['Ref']))Error(12," : No Valid Ref");
    }else{ //if pay ref already generated
        //Error("CE",$Param['PayRef']);
        //get the details
        $int = $dbo->SelectFirstRow("order_tb","TransNum,Amt","TransNum='".$dbo->SqlSafe($Param['PayRef'])."'");
    if(!is_array($int))Error(4,", Invalid Payment Reference");
    $int['Ref'] = $int['TransNum'];
    }
    
 
  
    
    $paytypeid = 1;//bank
    //bank print url
    if(isset($Param['PayOptionCard']) && $Param['PayOptionCard'] == 1){
        $rd = $__Root__."general/Payment/post.php?Ref=".$int['Ref']."&SubDir=".urlencode($dbo->Config['SubDir']);
        $paytypeid = 2; //card
        //Wallet will still come in - 3
    }else{
        $rd = $__Root__."general/Slip.php?folder=Payment&ItemNo=".$int['Ref']."&paper=A4&orientation=P&MT=4&MB=30&SubDir=".urlencode($dbo->Config['SubDir']);
    }
    //Error("CE",json_encode(["PayRef"=>$int['Ref'],"Amount"=>$int['Amt'],"Redirect"=>$rd,"PayOption"=>$paytypeid]));
    return ["PayRef"=>$int['Ref'],"Amount"=>$int['Amt'],"Redirect"=>$rd,"PayOption"=>$paytypeid];
}

//verify payment - R009
function VerifyPayment($Param){
    
    Underscored($Param);
    MapData($Param);
    session_start();
    global $dbo;global $__Root__;
    if(!isset($Param['PayRef']) || trim($Param['PayRef']) == "")Error(11,"jkk");
    //print data
    $ardata = "{Src:'{$__Root__}general/Slip.php?ItemNo=".urlencode($Param['PayRef'])."&folder=Payment&SubDir=".urlencode($dbo->Config['SubDir'])."',PayperType:'A4',Orientation:'P',MarginTop:4,MarginBottom:4}";


    //get the order details
    $orderDet = $dbo->SelectFirstRow("order_tb","","TransNum='".$dbo->SqlSafe($Param['PayRef'])."'");
    if(!is_array($orderDet))Error(4,", Invalid Payment Reference");
    $RegNo = $orderDet['RegNo'];
    if(isset($Param['RegNo']) && strtolower($Param['RegNo']) != strtolower($RegNo))Error(27);
    $PayID = $orderDet['ItemID'];
    if($Param['PayID'] != $PayID)Error(14);
    $paydet = HasPaidRef($Param['PayRef']);
    //return ["Status"=>"Paid"];
    if($paydet[0] != 1){ //payment not made
        if(isset($Param['VerifyScope']) && $Param['VerifyScope'] == "Student"){
          //get the student details
          //get the level
          $OtherDet = json_decode($orderDet["Info"],true);
          if(!is_null($OtherDet)){
              $StudyID = $OtherDet['StudyID'];
              $LevelID = $orderDet["Lvl"];
              $SemID = $orderDet["Sem"];
              $LevelName = LevelName($LevelID, $StudyID);
              $SemName = SemesterDescription($SemID);
              if($SemName == "UNKNOWN")$SemName = "FULL";
              return ["Status"=>"Payment Failed","PayRef"=>$Param['PayRef'],"RegNo"=>$RegNo,"PayID"=>$PayID,"Prog"=>$OtherDet['ProgName'],"RegLevel"=>6,"ImageErr"=>"notpaid.png","LevelName"=>$LevelName,"SemesterName"=>$SemName,"FAmt"=>number_format($orderDet["Amt"],2),"ItemName"=>$orderDet["ItemName"],"PrintData"=>$ardata,"AutoReg"=>[]];
          }else{
            Error(47," : ".$paydet[5]);
          }
        }else{
            Error(13," : ".$paydet[5]);
        }
    }else{
        //put details in session for further use
//$_SESSION['LRegNo'] = $RegNo;
//$_SESSION['LoginName'] = $RegNo;
$_SESSION['LPayID'] = $PayID;
$_SESSION['LPayRef'] = $Param['PayRef'];

if(!isset($Param['NextPageNum']))$Param['NextPageNum'] = 0;

if(isset($Param['VerifyScope']) && $Param['VerifyScope'] == "Student"){
    $OtherDet = json_decode($orderDet["Info"],true);
    if(!is_null($OtherDet)){
        $StudyID = $OtherDet['StudyID'];
        $LevelID = $orderDet["Lvl"];
        $SemID = $orderDet["Sem"];
        $LevelName = LevelName($LevelID, $StudyID);
        $SemName = SemesterDescription($SemID);
        if($SemName == "UNKNOWN")$SemName = "FULL";
        return ["Status"=>"Payment Successfull","PayRef"=>$Param['PayRef'],"RegNo"=>$RegNo,"PayID"=>$PayID,"Prog"=>$OtherDet['ProgName'],"RegLevel"=>6,"ImageErr"=>"paid.png","LevelName"=>$LevelName,"SemesterName"=>$SemName,"FAmt"=>number_format($orderDet["Amt"],2),"ItemName"=>$orderDet["ItemName"],"PrintData"=>$ardata,"AutoReg"=>[]];
    }else{
        Error(59);
    }
}else{
//To Tempoarily make the work uploadable
$candet = GetCandidate(["RegNo"=>$RegNo]);
  //set the payment ref and user regno in session
  return ["Status"=>"Paid","PayRef"=>$_SESSION['LPayRef'],"RegNo"=>$RegNo,"PayID"=>$PayID,"Prog"=>$candet["ProgrammeName"],"RegLevel"=>(int)$candet["RegLevel"],"NextPageNum"=>$Param['NextPageNum']];
}
      
    }
}

//check payment status
function CheckPayStatus($Param){
    session_start();
    global $dbo;
    if(!isset($Param['PayID']) || (int)$Param['PayID'] == 0)Error(11);
    if(!isset($Param['LevelID']) || (int)$Param['LevelID'] == 0)$Param['LevelID']=1;
    if(!isset($Param['SemesterID']) || (int)$Param['SemesterID'] == 0)$Param['SemesterID']=1;
    if(!isset($Param['SemesterPartID']) || (int)$Param['SemesterPartID'] == 0)$Param['SemesterPartID']=3;
    if(!isset($Param['PayDate']) || trim($Param['PayDate']) == "")$Param['PayDate']=NULL;
    if(!isset($Param['Deep']) || (is_string($Param['Deep']) && trim($Param['Deep']) == ""))$Param['Deep']=true;
    
    
    $studdet = [];
    if(!isset($Param['LoginName']) || trim($Param['LoginName']) == ""){
        //Error(5); 
          if(isset($_SESSION['LoginName']) && trim($_SESSION['LoginName']) != ""){
            $Param['LoginName'] = $_SESSION['LoginName'];
          }else{
           // Error(5);
          }
    }

          if(isset($Param['LoginName']) && trim($Param['LoginName']) != ""){
            if(!isset($Param['ProgID']) || (int)$Param['ProgID'] == 0)$Param['ProgID']=GetStudentProgIDForPay($Param['LoginName']);
            $getses = GetSchoolSession();

            //get the student progID
            // $progID = $dbo->SelectFirstRow("studentinfo_tb","ProgID","RegNo='".$dbo->SqlSafe($Param['LoginName'])."' OR JambNo='".$dbo->SqlSafe($Param['LoginName'])."'",MYSQLI_ASSOC);

            //$progID = !is_array($progID)?0:$progID['ProgID'];
            
            //query payhistory
            $payst = $dbo->SelectFirstRow("payhistory_tb","TransID,Amt","RegNo='".$dbo->SqlSafe($Param['LoginName'])."' AND Lvl=".$Param['LevelID']." AND ((Sem = ".$Param['SemesterID']." AND SemPart >= ".$Param['SemesterPartID'].") OR (Sem > ".$Param['SemesterID'].")) AND PayID=".$Param['PayID']." AND ProgID=".$Param['ProgID']);
            //$payst = $dbo->SelectFirstRow("payhistory_tb","TransID","RegNo='".$dbo->SqlSafe($Param['LoginName'])."' AND Lvl=".$Param['LevelID']." AND ((Sem = ".$Param['SemesterID']." AND SemPart >= ".$Param['SemesterPartID'].") OR (Sem > ".$Param['SemesterID'].")) AND Ses = ".$getses['SesID'] . " AND PayID=".$Param['PayID']);
            
            if(is_array($payst)){ //paid

              return ["Status"=>"Paid","PayRef"=>$payst['TransID'],"Amount"=>$payst['Amt'],"FAmount"=>number_format($payst['Amt'],2)];
            }else{
                
                //check if exist in order
               // $ordst = $dbo->SelectFirstRow("order_tb","TransNum","RegNo='".$dbo->SqlSafe($Param['LoginName'])."' AND Lvl=".$Param['LevelID']." AND (Sem = ".$Param['SemesterID']." AND SemPart = ".$Param['SemesterPartID'].") AND Ses = ".$getses['SesID'] . " AND ItemID=".$Param['PayID']);
               if($Param['Deep']){ //if deep verification - check gatway
               // Error(2,"Is Deep ".$Param['Deep'] );
                $ordst = $dbo->SelectFirstRow("order_tb","TransNum","RegNo='".$dbo->SqlSafe($Param['LoginName'])."' AND Lvl=".$Param['LevelID']." AND (Sem = ".$Param['SemesterID']." AND SemPart = ".$Param['SemesterPartID'].")  AND ItemID=".$Param['PayID']." AND ProgID=".$progID);
                
                
                if(!is_array($ordst))return ["Status"=>"NotPaid","PayRef"=>""];

                
                $Ref = $ordst['TransNum'];
               // if($Param['cnt'] == 3){
                  //  $paydet = HasPaidRef2($Ref);
                   // Error("CE",json_encode($paydet)); 
               // }else{
                    $paydet = HasPaidRef($Ref);
               // }
                
               
                //return ["Status"=>"Paid"];
                if($paydet[0] != 1){ //payment not made
                    //Error(4,json_encode($paydet));
                    return ["Status"=>"NotPaid","PayRef"=>$Ref];
                }else{
                    
                    return ["Status"=>"Paid","PayRef"=>$Ref];
                }
               }else{
                return ["Status"=>"NotPaid","PayRef"=>""];
               }
                
            }

          }
}

//Get Candidate Details - R010
function GetCandidate($Param){
    global $dbo; global $__Root__;
    Underscored($Param);
    MapData($Param);
    //Error(15, " : ".json_encode($Param));
    session_start();
    if(isset($Param['RegNo'])){
        //check if regno is phone or email
        $regarr = explode("@",$Param['RegNo']);
        $isemail = [];
        $isphone = [];
        if(count($regarr) > 1){ //if the type of regno is email, allow phone number
          $isphone = [1];
        }else{
            $isemail = [1];
        }
        $RegNo = $dbo->SqlSafe($Param['RegNo']);
       
        //get candidate details from pstudent info
        $canddet = $dbo->SelectFirstRow("pstudentinfo_tb","","RegNo='$RegNo' OR JambNo='$RegNo'",MYSQLI_ASSOC);
        if(!is_array($canddet)){ //if not found in pstudent info
          //the check in payee_tb
          $canddet = $dbo->SelectFirstRow("payee_tb","","PayeeID='$RegNo'");
          if(is_array($canddet)){
            $cand = [];
            //get all the field name
            $columns = $dbo->RunQuery("SHOW COLUMNS FROM pstudentinfo_tb");
            while($indcol = $columns[0]->fetch_assoc()){
                if($indcol['Field'] == "id")continue;
                $cand[$indcol['Field']] = "";
            }


            $CNames = explode(" ",$canddet['Name']);
               $cand['SurName'] = trim($CNames[0]);$cand['FirstName'] = trim($CNames[1]);
               $CNames[0] = "";$CNames[1] = "";
               $cand['OtherNames'] = trim(implode(" ",$CNames));
          }else{
              Error(15);
          }
          $canddet = $cand;
          $canddet["Occupation"] = "";
          $canddet["Degree"] =  "";
          $canddet["AreaofSpecial"] = "";//ResearchTopic
          $canddet["ResearchTopic"] = "";
          $canddet["FormerName"] = "";
          $canddet["StudyModeFullTime"] = "";
          $canddet["StudyModePartTime"] = "";
          $canddet["StudyMode"] = "";
          $canddet["FacultyName"] = "";
          $canddet["ProgrammeName"] = "";
          $canddet["Address"] = "";
          $canddet["OtherAddress"] = "";
          //$canddet["StudyID"] = "";
        }else{
            //return ["RegNo"=>"ab_keje@yahoo.com","SurName"=>$canddet["SurName"]];
            $otherdet = trim($canddet['OtherDet'])==""?[]:json_decode($canddet['OtherDet'],true);
            //$RtnData["CandFullName"] = $canddet['SurName']." ".$canddet['FirstName']." ".$canddet['OtherNames'];
            //$RtnData["CandFullName"] = $canddet['SurName']." ".$canddet['FirstName']." ".$canddet['OtherNames'];
           
            $canddet["DOB"] = MysqlDateDecode($canddet['DOB']);
            $canddet["GenderMale"] = $canddet['Gender'] != "F"?"checked":"";
            $canddet["GenderFemale"] = $canddet['Gender'] == "F"?"checked":"";
            $canddet['Gender'] = $canddet['Gender'] != "F"?"Male":"Female";
            $canddet["Occupation"] = isset($otherdet['Occupation'])?$otherdet['Occupation']:"";
            $canddet["FormerName"] = isset($otherdet['FormerName'])?$otherdet['FormerName']:"";
            $degree = "";
            if(isset($otherdet['Degree'])){
                 $degree = $dbo->SelectFirstRow("school_degrees_tb","","ID=".$otherdet['Degree']);
            $degree = is_array($degree)?$degree['Name']:"";
            }
           
            $canddet["Degree"] = $degree;
            $canddet["AreaofSpecial"] = isset($otherdet['AreaofSpecial'])?$otherdet['AreaofSpecial']:"";//ResearchTopic
            $canddet["ResearchTopic"] = isset($otherdet['ResearchTopic'])?$otherdet['ResearchTopic']:"";
            $canddet["StatusMarried"] = $canddet['MaritalStatus'] != "S"?"checked":"";
            $canddet["StatusSingle"] = $canddet['MaritalStatus'] == "S"?"checked":"";//StudyModeFullTime
            $canddet["StudyModeFullTime"] = (isset($otherdet['StudyModeFullTime']) && (int)$otherdet['StudyModeFullTime']==1)?"checked":"";
            $canddet["StudyModePartTime"] = (isset($otherdet['StudyModePartTime']) && (int)$otherdet['StudyModePartTime']==1)?"checked":"";
            $canddet["StudyMode"] = $canddet["StudyModeFullTime"] == "checked"?"Full Time":"Part Time";
            //$canddet["Nationality"] = $canddet['Nationality'];
            $canddet["StateID"] = $canddet['StateId'];
            $canddet["Address"] = $canddet['Addrs'];
            $canddet["OtherAddress"] = isset($otherdet['OtherAddress'])?$otherdet['OtherAddress']:"";
            if(isset($canddet["ProgID"]) && (int)$canddet["ProgID"] > 0){
               $admidet = $dbo->SelectFirstRow("fac_tb f, programme_tb p, dept_tb d","f.FacName,p.ProgName","p.ProgID=".$canddet["ProgID"]." AND p.DeptID = d.DeptID AND f.FacID = d.FacID",MYSQLI_ASSOC);
               if(!is_array($admidet)){
                $canddet["FacultyName"] = "";
                $canddet["ProgrammeName"] = "";
               }else{
                $canddet["FacultyName"] = $admidet["FacName"];
                $canddet["ProgrammeName"] = $admidet["ProgName"];
               }
            }

        }
        //get studyid from programme id
        if(isset($canddet["ProgID"]) && (int)$canddet["ProgID"] > 0 && (int)$canddet["StudyID"] < 1){
            $canddet["StudyID"] = GetStudyID($canddet["ProgID"]);
        }

        if((int)$canddet["StudyID"] == 0 && isset($Param["StudyID"]) && (int)$Param["StudyID"] > 0)$canddet["StudyID"] = $Param["StudyID"];
        $rd ="{$__Root__}general/Slip.php?folder=Candidate&regno=".$RegNo."&paper=A4&orientation=P&MT=4&MB=30&SubDir=".urlencode($dbo->Config['SubDir']);
        $canddet["RedirectURL"] = $rd;
        $sub = urlencode($dbo->Config['SubDir']);
        $canddet["RedirectData"] = "{Src:'{$__Root__}general/Slip.php?folder=Candidate&regno={$RegNo}&SubDir={$sub}',PayperType:'A4',Orientation:'P',MarginTop:4,MarginBottom:30}";
        $canddet["AllowPhone"] = $isphone;
        $canddet["AllowEmail"] = $isemail;
      return $canddet;

    }else{
        //Error(15, " : ".json_encode($Param));
        Error(15);
    }
  //return $_SESSION;

}

//function to get studyid by progid
function GetStudyID($progid){
    global $dbo;
    $study = $dbo->SelectFirstRow("fac_tb f, dept_tb d, programme_tb p","f.StudyID","f.FacID = d.FacID AND d.DeptID = p.DeptID AND p.ProgID = $progid");
    if(is_array($study))return $study['StudyID'];
    return 0;
}
//Get State Of Origin - R011
function GetStateOfOrigin($Param){
    global $dbo;
    //check if country id supplied
    $conty = (isset($Param['CountryID']) && (int)$Param['CountryID'] > 0)?$Param['CountryID']:1;
    $selected = (isset($Param['SelectID']) && (int)$Param['SelectID'] > 0)?$Param['SelectID']:0;
    //get all state of origin
    $states = $dbo->Select("state_tb","","CountryID=".$conty);
    if(!is_array($states))Error(4);
    $StateReturn = [];
    while($state = $states[0]->fetch_assoc()){
        $state['Selected'] = "";
        if((int)$state['StateID'] == (int)$selected){
            $state['Selected'] = "selected";
            array_unshift($StateReturn,$state);
        }else{
            $StateReturn[] = $state;
        }
    }

    return $StateReturn;
}

//Get Local government - R012
function GetLGAreas($Param){
    global $dbo;
    if(isset($Param['StateID']) && (int)$Param['StateID'] > 0){
      //select all
      $lgas = $dbo->Select("lga_tb","","StateID=".$Param['StateID']);
      if(!is_array($lgas))Error(4);
      return $dbo->FetchAll($lgas[0],MYSQLI_ASSOC);
    }else{
        return [];
    }

}

//Get Local government - R013
function SaveCandidate($Param){
   Underscored($Param);
    session_start();
    $RegNo = "";
    /* if(!isset($_SESSION['RegNo']) || trim($_SESSION['RegNo']) == ""){ 
        if(!isset($Param['RegNo']) || trim($Param['RegNo']) == "")Error(11);
        $_SESSION['RegNo'] = $Param['RegNo'];
    }else{
        $Param['RegNo'] = $_SESSION['RegNo'];
    } */
    if(!isset($Param['RegNo']) || trim($Param['RegNo']) == ""){
        if(!isset($Param['RegNo_Appl']) || trim($Param['RegNo_Appl']) == "")Error(11);
        $RegNo = $Param['RegNo_Appl'];
    }else{
        $RegNo = $Param['RegNo'];
    }
    $rst = SaveCandidateReal($RegNo,$Param);
    if($rst === true){
       // $_SESSION['RegNo'] = $Param['RegNo'];
      return $Param;
    }
    Error(11," : ".$rst);

}

//Private - Form Cand Queary
function SaveCandidateReal($RegNo,$Data){
    global $dbo;global $Fields;
    if(!isset($RegNo))Error(15);
    //confirm if candidate already exist
    $CRegNo = $dbo->SqlSafe($RegNo);
    $cand = $dbo->SelectFirstRow("pstudentinfo_tb","","RegNo = '$CRegNo' OR JambNo = '$CRegNo'",MYSQLI_ASSOC);
    $Otherdet = [];
    $exist = false;
    if(is_array($cand)){
        $exist = true;
        //exist
        //get the other details
        $Otherdet = (trim($cand['OtherDet']) != '')?json_decode($cand['OtherDet'],true):[];
    }else{
        $cand = [];
        //get all the field name
        $columns = $dbo->RunQuery("SHOW COLUMNS FROM pstudentinfo_tb");
        while($indcol = $columns[0]->fetch_assoc()){
            if($indcol['Field'] == "id")continue;
            if($indcol['Type'] == "date" ){
                $cand[$indcol['Field']] = date("Y-m-d");
            }elseif(substr($indcol['Type'], 0, 4) == "int(" ){
                $cand[$indcol['Field']] = 0;
            }else{
                $cand[$indcol['Field']] = "";
            }
            
        }
        //not exist
    }
   // Error(11," : ".json_encode($cand));
    //package all data as required
    if(!is_array($Data))Error(11);
    $candData = [];
   
    foreach($Data as $UField => $Udata){
        $UFieldarr = explode("_",$UField);
        $RealField = "";
    if(count($UFieldarr) > 1){
        array_pop($UFieldarr);
        $RealField = implode("_",$UFieldarr);
    }else{
        $RealField = $UFieldarr[0];
    }

    //$candData[] = $RealField;
        $RealField = isset($Fields[$RealField])?$Fields[$RealField]:$RealField;
        //$candData = [];
        switch ($RealField) {
            case "Credentials":
            $filename = str_replace(array("/",'\\'),"_",$RegNo."_credential");
            /* if(file_exists("../../../../".$dbo->Config['SubDir'].$dbo->Config['Require']."Image/")){
        Error(53," - ../../../../".$dbo->Config['SubDir'].$dbo->Config['Require']."Image/ : EXIST");
    }else{
        Error(53," - ../../../../".$dbo->Config['SubDir'].$dbo->Config['Require']."Image/ : NOT EXIST");
    } */
              //try uploading passport
              $rst = Uploader("../../../../".$dbo->Config['SubDir']."Files/UserImages/PUTME/",$UField,$filename);
              
              //Error(17," ".json_encode($rst));
              if(count($rst["Failed"]) > 0)Error(17," : ".$rst["Failed"][$UField]);
              $Otherdet["Credentials"] = $rst["Success"][$UField];
              break;
              case "OtherCredentials":
              $filename = str_replace(array("/",'\\'),"_",$RegNo."_other_credential");
              //
                //try uploading passport
                $rst = Uploader("../../epconfig/UserImages/PUTME/",$UField,$filename);
                //Error(17," ".json_encode($rst));
                if(count($rst["Failed"]) > 0)Error(17," : ".$rst["Failed"][$UField]);
                $Otherdet["OtherCredentials"] = $rst["Success"][$UField];
                break;
            case "Passport":
            case "Passport_Appl":
                
            $filename = str_replace(array("/",'\\'),"_",$RegNo);
            
              //try uploading passport
              $rst = Uploader("../../../../".$dbo->Config['SubDir']."Files/UserImages/PUTME/",$UField,$filename);
              //Error(17," ".json_encode($rst));
              if(count($rst["Failed"]) > 0)Error(17," : ".$rst["Failed"][$UField]);
              if(isset($rst["Success"][$UField])){
              
              $parr = explode('/UserImages/',$rst["Success"][$UField]);
              //resize image
              $newimg = ResizeImage($rst["Success"][$UField],300,300);
              $cand['Passport'] = count($parr) == 2?"UserImages/".$parr[1]:$rst["Success"][$UField];
              }
              //$cand['Passport'] = substr($rst["Success"][$UField],3);
            break;
            case "FullName":
               //check if full name then break
               $CNames = explode(" ",$Udata);
               $cand['SurName'] = trim($CNames[0]);$cand['FirstName'] = trim($CNames[1]);
               $CNames[0] = "";$CNames[1] = "";
               $cand['OtherNames'] = trim(implode(" ",$CNames));
                break;
                case "LevelID":
                    //Error("CE",$Udata);
                    $StartSes = GetStartSesByLevel($Udata);
                    $cand['StartSes'] = $StartSes;
                        break;
            case "DOB":
            $cand['DOB'] = MysqlDateEncode($Udata);
            
                break;
                case "RegDate":
            $cand['RegDate'] = MysqlDateEncode($Udata);
                break;
                case "AdminDate":
            $cand['AdminDate'] = MysqlDateEncode($Udata);
                break;
            case "GenderMale":
            $cand['Gender'] =  ((int)$Udata == 1)?"M":"F";
           // $candData[] = $UField;
                break;
            case "StatusMarried":
            $cand['MaritalStatus'] =  ((int)$Udata == 1)?"M":"S";
            break;
            default:
            if(array_key_exists($RealField,$cand)){
               // if(isset($cand[$UFieldarr[0]]) || is_null($cand[$UFieldarr[0]])){
                //array_key_exists
                $cand[$RealField] = $Udata;
                //$candData[] = $UFieldarr[0];
                
            }else{
               if(trim($RealField) != "")$Otherdet[$RealField] = $Udata;
                //Error(11,$UFieldarr[0]);
            }
        }
    }
    //Error(11," : ".json_encode($cand));
    $cand['OtherDet'] = json_encode($Otherdet);
    if($exist){
        $upd = $dbo->Update("pstudentinfo_tb",$cand,"id=".$cand['id']);
        if(is_array($upd)){
            return true;
        }else{
            return $upd;
        }
    }else{
        $ins = $dbo->Insert("pstudentinfo_tb",$cand);
        if($ins == "#"){
            return true;
        }else{
            return $ins;
        }
    }
    
}

//Private
//Resolve underscore parameter name
function Underscored(&$Param){
  foreach($Param as $Key=>$Val){
      //check if system data
      if(substr($Key,0,2) == "__")continue;
      //break down keys
      $Keyus = explode("_",$Key);
      if(count($Keyus) > 1){
          array_pop($Keyus);
          $remkey = implode("_",$Keyus);
          if(!isset($Param[$remkey]))$Param[$remkey] = $Val;
      }

  }

}

//private
//Handle _EPAPI_MAPPING_
function MapData(&$Param){
    if(!isset($Param['_EPAPI_MAPPING_']))return;
  $mappins = is_array($Param['_EPAPI_MAPPING_'])?$Param['_EPAPI_MAPPING_']:[$Param['_EPAPI_MAPPING_']];
  if(count($mappins) > 0){
      foreach($mappins as $imap){
          //get multiple mapping
          $multmapp = explode(";",$imap);
          foreach($multmapp as $map){
            $mapdata = explode("=>",$map);
          if(count($mapdata) > 1){
              //main map
              $mainmap = "";
              foreach($mapdata as $indmap){
                $indmap = trim($indmap);
                if($indmap != ""){
                   if($mainmap == ""){
                    $mainmap = $indmap;
                   }else{
                    if(isset($Param[$mainmap])){
                      $Param[$indmap] = $Param[$mainmap];
                    } 
                   }
                }
              }
          }
          }
          
      }
  }
}

//Get all faculties - R014
function GetFaculty($Param){
   // Error(4,$Param['ProgID']);
    global $dbo;
    $studycond = (isset($Param['StudyID']) && (int)$Param['StudyID'] > 0)?"StudyID=".$dbo->SqlSafe($Param['StudyID']):"1=1";
    $facs = $dbo->Select("fac_tb","",$studycond);
    //Error(4,$studyid);
    if(!is_array($facs))Error(4);
    return $dbo->FetchAll($facs[0],MYSQLI_ASSOC);
}

//Get all programmes by deptid - R015
function GetProgrammeByFaculty($Param){
    global $dbo;
    if(!isset($Param['FacID']) || (int)$Param['FacID'] < 1)Error(11);
    $FacID = $Param['FacID'];
    $facs = $dbo->Select("programme_tb p, dept_tb d","p.*","d.FacID=".$dbo->SqlSafe($FacID)." AND p.DeptID = d.DeptID");
    if(!is_array($facs))Error(4);
    return $dbo->FetchAll($facs[0],MYSQLI_ASSOC);
}

//create a unique record entering - R016
function CreateUniqueRecord($Param){
    Underscored($Param);
    MapData($Param);
    //Error(11," - ".json_encode($Param));
    //Param - {UniqueName:['uname'],UniqueKey:[''],UniqueDetail:['']}
    global $dbo;
    if(!isset($Param['UniqueName']) || (is_string($Param['UniqueName']) && trim($Param['UniqueName']) == "") || (is_array($Param['UniqueName']) && count($Param['UniqueName']) < 1))Error(11);
    if(!isset($Param['UniqueKey']))$Param['UniqueKey']="";
    if(!isset($Param['UniqueDetails']))$Param['UniqueDetails']="";
    //check for multiple UniqueName
    $Param['UniqueName'] = is_array($Param['UniqueName'])?$Param['UniqueName']:[$Param['UniqueName']];
    $Param['UniqueKey'] = is_array($Param['UniqueKey'])?$Param['UniqueKey']:[$Param['UniqueKey']];//
    $Param['UniqueDetails'] = is_array($Param['UniqueDetails'])?$Param['UniqueDetails']:[$Param['UniqueDetails']];
    $Param['OtherInfo'] = is_array($Param['OtherInfo'])?$Param['OtherInfo']:[$Param['OtherInfo']];
    $UniqueEntry = [];
   
    foreach($Param['UniqueName'] as $key=>$uniquename){
        if(trim($uniquename) == "")continue;
         //check if unique name already exist
         $uname = $dbo->SelectFirstRow("unique_tb","","UniqueName='$uniquename'");
         if(is_array($uname)){
            $UniqueEntry[] = $uname;
            continue;
         }
         //get other details
         $uniquekey = isset($Param['UniqueKey'][$key])?$Param['UniqueKey'][$key]:"";
         if(trim($uniquekey) == ""){ //if not set generate random value
            do{
                $uniquekey = $dbo->GenerateString(10,10," /\\&=?~`!@#$%^*()-+{}[]:;\"'<>,.");
            }while(is_array($dbo->SelectFirstRow("unique_tb","","UniqueKey='$uniquekey'")));
         }else{
             //check if already exist
            $exist = $dbo->SelectFirstRow("unique_tb","","UniqueKey='$uniquekey'");
            if(is_array($exist))Error(18);
         }
         $uniquedet = isset($Param['UniqueDetails'][$key])?$Param['UniqueDetails'][$key]:$Param['UniqueDetails'][0];
         if(is_array($uniquedet))$uniquedet = json_encode($uniquedet);
         $otherinfo = isset($Param['OtherInfo'][$key])?$Param['OtherInfo'][$key]:$Param['OtherInfo'][0];
         if(is_array($otherinfo))$otherinfo = json_encode($otherinfo);
         //insert into database
         $inst = $dbo->Insert("unique_tb",["UniqueName"=>$uniquename,"UniqueKey"=>$uniquekey,"UniqueDetails"=>$uniquedet,"OtherInfo"=>$otherinfo,"OnlineInfo"=>'{}']);
         if($inst == "#"){
            $UniqueEntry[] = ["UniqueName"=>$uniquename,"UniqueKey"=>$uniquekey,"UniqueDetails"=>$uniquedet,"OtherInfo"=>$otherinfo];
        
            if(isset($Param['SendMailUnique']) && (int)$Param['SendMailUnique'] > 0 && isset($Param['Mail']) && isset($Param['ToAddress'])){
                $TAdress = is_array($Param['ToAddress'])?$Param['ToAddress'][$key]:$Param['ToAddress'];
                $Mail = $Param['Mail'];
                $FName= isset($Param['FromName'])?$Param['FromName']:"";
                $Subject= isset($Param['Subject'])?$Param['Subject']:"";
                $mailparam = array_merge($Param,["Mail"=>$Mail,"ToAddress"=>$TAdress,"FromName"=>$FName,"Subject"=>$Subject,"UniqueName"=>$uniquename,"UniqueKey"=>$uniquekey,"UniqueDetails"=>$uniquedet,"OtherInfo"=>$otherinfo,"OnlineInfo"=>'{}']);
                 $mailparam["UniqueName"] = $uniquename;
                 
                $sends = SendMail($mailparam);
                if($sends !== true){
                   // Error();
                }
            }
         }else{
            //Error(18," : ".$inst);
         }
    }

return $UniqueEntry;
}

//check a unique record entering - R017
function CheckUniqueEntry($Param){
    Underscored($Param);
    MapData($Param);
    global $dbo;
    if(!isset($Param['UniqueName']) || trim($Param['UniqueName']) == "" || !isset($Param['UniqueKey']) || trim($Param['UniqueKey']) == "")Error(11);
    $UniqueName = $dbo->SqlSafe($Param['UniqueName']);
    $UniqueKey = $dbo->SqlSafe($Param['UniqueKey']);
    //get the unique details
    $udet = $dbo->SelectFirstRow("unique_tb","","UniqueName='$UniqueName' AND UniqueKey='$UniqueKey'",MYSQLI_ASSOC);
    if(!is_array($udet))Error(19);
    if((int)$udet["Enable"] == 0)Error(20);
    $udet["OnlineInfo"] = is_null($udet["OnlineInfo"])?[]:json_decode($udet["OnlineInfo"],true);
    return $udet;
}

//update unique details - R018
function UpdateUniqueEntry($Param){
    Underscored($Param);
    MapData($Param);
    if(!isset($Param['UniqueID']) || (int)$Param['UniqueID'] == 0)Error(11);
    global $dbo;
    //get the unique details
    $undet = $dbo->SelectFirstRow("unique_tb","UniqueName,UniqueKey,UniqueDetails,OtherInfo,OnlineInfo,Enable","UniqueID=".$dbo->SqlSafe($Param['UniqueID']),MYSQLI_ASSOC);
    if(!is_array($undet))Error(19);
    $OnlineInfo = json_decode($undet['OnlineInfo'],true);
    //loop through all param and update as required
    foreach($Param as $Pkey=>$PVal){
        if(isset($undet[$Pkey])){
            $undet[$Pkey] = $PVal;
        }else{
            $OnlineInfo[$Pkey] = $PVal; 
        }
    }
    $undet['OnlineInfo'] = json_encode($OnlineInfo);

    //run update
    $upd = $dbo->Update("unique_tb",$undet,"UniqueID=".$dbo->SqlSafe($Param['UniqueID']));
    if(is_array($upd)){
        return array_merge($undet,$OnlineInfo);
    }else{
        Error(4," : ".$upd);
    }
}

//Send Mail - R019
function SendMail($Param){
    
    Underscored($Param);
    MapData($Param);
    if(!isset($Param['ToAddress']) || !isset($Param['Mail'])){
        if(isset($Param['Optional']) && $Param['Optional'] == true){
            return ["Status"=>"Not Sent","ToAddress"=>""];
        }
        Error(11);
    }
    //if(file_exists($Param['Mail'])){
        //Error(21," : Exist");
        $Mail = file_get_contents($Param['Mail']);
        $Param['Mail'] = "";
        //fill in placeholders
        foreach($Param as $field=>$val){
            if(!is_string($val) && !is_numeric($val))continue;
            $Mail = str_replace("{{".$field."}}",$val,$Mail);
        }

        //Error(11,json_encode($Param));
        
   // }
    if(!isset($Param['FromName']))$Param['FromName'] = "Eduporta";
    if(!isset($Param['Subject']))$Param['Subject'] = "";
    $Param['ToAddress'] = is_array($Param['ToAddress'])?$Param['ToAddress']:[$Param['ToAddress']];
    $sent = 0;
    foreach($Param['ToAddress'] as $toaddr){
        if(trim($toaddr) == "")continue;
        $sendmail = genPHPMEmail($toaddr,$Param['FromName'],$Param['Subject'],$Mail);
    if($sendmail !== true){
        if(isset($Param['Optional']) && $Param['Optional'] == true){
            return ["Status"=>"Not Sent","ToAddress"=>""];
        }
        Error(21," : ".$toaddr);
    }
    $sent++;
    }
    if($sent > 0){
      return ["Status"=>"Sent","ToAddress"=>$Param['ToAddress']];  
    }
    if(isset($Param['Optional']) && $Param['Optional'] == true){
        return ["Status"=>"Not Sent","ToAddress"=>""];
    }
    Error(21," : No Sent Mail");
    
 
}

//private mailing
//generate emil
function genPHPMEmail($mailto="",$from_name="Eduporta",$subject="Eduporta Mail",$msg="Eduporta"){
    if(trim($mailto) == "")return "No Destination Mail Address Supplied";
    $mailto = $mailto;
    $from_name = $from_name;
    $from_mail = "taquatech@gmail.com";
    $subject = $subject;
    $message = $msg;
    $boundary = "XYZ-" . date('dmYis') . "-ZYX";
    $header = "--$boundary\r\n";
    $header .= "Content-Transfer-Encoding: 8bits\r\n";
    $header .= "Content-Type: text/html; charset=ISO-8859-1\r\n\r\n";
    $header .= "$message\r\n";
    $header .= "--$boundary\r\n";

    $header2 = "MIME-Version: 1.0\r\n";
    $header2 .= "From: ".$from_name." \r\n";
    $header2 .= "Return-Path: ".$from_mail." \r\n";
   // $header2 .= 'Cc: ubonge80@gmail.com' . "\r\n";
    $header2 .= "Content-Type: multipart/mixed; boundary=\"$boundary\"\r\n";
    $header2 .= "$boundary\r\n";
    $getRespons = mail($mailto,$subject,$header,$header2,"-r".$from_mail);
    if($getRespons){
        return true;
    }else{
        return "Not Sent";
    }
}

//#R020
function GetSchoolDegrees($param){
    
    global $dbo;
    //get all school degrees
    $deg = $dbo->Select("school_degrees_tb","ID as DegID, Name as DegName");
    if(!is_array($deg))Error(4);
    return $dbo->FetchAll($deg[0],MYSQLI_ASSOC);
}

//#R021
function VerifyCandidate($Param){
    Underscored($Param);
    global $__Root__;
    if(!isset($Param['RegNo']) || trim($Param['RegNo']) == "")Error(11);
    global $dbo;
    //get candidate from student info
    $cand = $dbo->SelectFirstRow("pstudentinfo_tb","","RegNo='".trim($dbo->SqlSafe($Param['RegNo']))."' OR JambNo='".trim($dbo->SqlSafe($Param['RegNo']))."'",MYSQLI_ASSOC);
    if(!is_array($cand))Error(23); //candidate doesnot exist
    if((int)$cand['RegLevel'] < 6)Error(24); //incomplete application
    if((int)$cand['admitted'] < 1)Error(25); //Candidate Not Yet Admitted

    //check if account already created
    $stud = $dbo->SelectFirstRow("studentinfo_tb","","RegNo='".trim($dbo->SqlSafe($Param['RegNo']))."' OR JambNo='".trim($dbo->SqlSafe($Param['RegNo']))."'");
    if(is_array($stud)){
        if(trim($stud['RegNo']) == "")$stud['RegNo'] = $stud['JambNo'];
//confirm access code
$accesscode = $dbo->SelectFirstRow("accesscode_tb","","JambNo='".$stud['RegNo']."' OR JambNo = '".$stud['JambNo']."'");
if(is_array($accesscode)){
   // Error(0,json_encode($accesscode));
    $cand["NRegNo"] = $accesscode['JambNo'];
    $cand["NextPageNum"] = 4; 
    $rdata = "{Src:'{$__Root__}general/Slip.php?regno=".urlencode($accesscode['JambNo'])."&folder=Form&SubDir=".urlencode($dbo->Config['SubDir'])."',PayperType:'A4',Orientation:'P',MarginTop:4,MarginBottom:4}";
    $cand["NRedirectData"] = $rdata;
    $ardata = "{Src:'{$__Root__}general/Slip.php?RegNo=".urlencode($accesscode['JambNo'])."&folder=AcceptLetter&SubDir=".urlencode($dbo->Config['SubDir'])."',PayperType:'A4',Orientation:'P',MarginTop:4,MarginBottom:4}";
    $cand["ARedirectData"] = $ardata;
        return $cand;
    //Error(26); //Student Account Already Created
}

    }
    //Error(23);
    //check if payment ordered
    //$cand = $dbo->SelectFirstRow("order_tb","","");
    if((int)$cand['Accept'] == 1){
        $cand["NextPageNum"] = 3;
        return $cand;
    }
    return $cand;

    
    
    
    // return ["NextPageNum"=>4];
}

//#R022
function AcceptAdmission($Param){
    Underscored($Param);
    if(!isset($Param['RegNo']) || trim($Param['RegNo']) == "")Error(11);
    global $dbo;
    //get candidate from student info
    $cand = $dbo->SelectFirstRow("pstudentinfo_tb","","RegNo='".trim($dbo->SqlSafe($Param['RegNo']))."' OR JambNo='".trim($dbo->SqlSafe($Param['RegNo']))."'");
    if(!is_array($cand))Error(23,$Param['RegNo']); //candidate doesnot exist
    $upd = $dbo->Update("pstudentinfo_tb",["Accept"=>1,"AdminDate"=>date("Y-m-d")],"id=".$cand['id']);
    if(!is_array($upd))Error("CE","Error while updating Acceptance.");
    return ["RegNo"=>$Param['RegNo']];

}

//#R023
function CandidateToStudent($Param){
    global $__Root__;
   // Error(23,json_encode($Param));
    /* $RegNo = $Param['RegNo'];
    $rd ="Slip.php?regno=".$RegNo."&folder=Form&paper=A4&orientation=P&MT=4&MB=30";
    // $canddet["RedirectURL"] = $rd;
     $rdata = "{Src:'Slip.php?regno={$RegNo}&folder=Form',PayperType:'A4',Orientation:'P',MarginTop:4,MarginBottom:30}";
     return ["NextPageNum"=>4,"RegNo"=>$RegNo,"RedirectURL"=>$rd,"RedirectData"=>$rdata]; */
    $vercand = VerifyCandidate($Param); //verify candidate
    
    if($vercand["NextPageNum"] == 3){ //if verified successfully
        
        Underscored($Param);
        //if(!isset($Param['RegNo']) || trim($Param['RegNo']) == "")Error(11);
        global $dbo;

        //2. create candidate details in studinfo
        //get the structure of student info
        $upcand = [];
       
        //get all the field name
        $columns = $dbo->RunQuery("SHOW COLUMNS FROM studentinfo_tb");
        while($indcol = $columns[0]->fetch_assoc()){
            if($indcol['Field'] == "id")continue;
            if($indcol['Field'] == "RegNo"){$upcand['RegNo'] = "";continue;}
            if($indcol['Field'] == "JambNo"){$upcand['JambNo'] = $Param['RegNo'];continue;}
            if($indcol['Field'] == "RegDate")$vercand[$indcol['Field']] = date('Y-m-d');
            if($indcol['Field'] == "AutoGenReg")$vercand[$indcol['Field']] = 'FALSE';
            if($indcol['Field'] == "AutoNum")$vercand[$indcol['Field']] = 0;
           /*  if($indcol['Field'] == "ClassID"){
                //add student to a class
                $vercand[$indcol['Field']] = 1;
            } */
            if(isset($vercand[$indcol['Field']])){
                $upcand[$indcol['Field']] = $vercand[$indcol['Field']];
            }else{
                $upcand[$indcol['Field']] = '';
            }
        }
        $JambNo = $upcand['JambNo'];
     //generate jambno
     //Use Random number instead of phone number
     do{
        //generate a random number
        $JambNo = strtoupper(substr( $upcand['SurName'],0,2)).mt_rand(100000,999999);
        $chk = $dbo->SelectFirstRow("studentinfo_tb","id","RegNo='".$dbo->SqlSafe($JambNo)."' OR JambNo='".$dbo->SqlSafe($JambNo)."'");
    }while(is_array($chk));

    //update JambNo
foreach(["order_tb","payhistory_tb"] as $uptb){
  $up = $dbo->Update($uptb,["RegNo"=>$JambNo],"RegNo='{$upcand['JambNo']}'");
}

$upcand['JambNo'] = $JambNo;
    

        $currSes = CurrentSes();
            //$upcand['StartSes'] = $currSes['SesID'];
        //clean data
        if((int)$upcand['StartSes'] == 0){
           // $currSes = CurrentSes();
            $upcand['StartSes'] = $currSes['SesID'];
        } 

        $progid = (int)$upcand['ProgID'];

        if((int)$upcand['StudyID'] == 0){
 //get the progid

 $facdet = $dbo->RunQuery("SELECT f.StudyID FROM fac_tb f, dept_tb d, programme_tb p WHERE f.FacID = d.FacID AND d.DeptID = p.DeptID AND p.ProgID = $progid");
 
//Error("CE",$ClassID);
 if(is_array($facdet)){
     $facrdet = $facdet[0]->fetch_assoc();
     $upcand['StudyID'] = $facrdet['StudyID'];
 }
        }

        //Add Student to Class
        //***************************
        //get the total already registered in the class
 $toreg = $dbo->SelectFirstRow("studentinfo_tb","COUNT(id) as Tot","ProgID=$progid AND StartSes={$upcand['StartSes']} AND RegLevel >= 6");
 $ClassID = 0;
 if(is_array($toreg)){
//get total all the available classes
$clases = $dbo->Select("studentclass_tb","ID,Capacity","ProgID=$progid");

if(is_array($clases) && $clases[1] > 0){ //if clases exist
   //get all calses
   while($indclass = $clases[0]->fetch_assoc()){
     $capaci = (int)$indclass['Capacity'];
     
      
        if((int)$toreg['Tot'] < $capaci){ // if  space available
            $ClassID = $indclass['ID'];
        break;
      
      }
   }
}
 }
 $upcand['ClassID'] = $ClassID ;
 //***************************
        if((int)$upcand['RegID'] == 0)$upcand['RegID'] = 1;
        if((int)$upcand['AdmSes'] == 0)$upcand['AdmSes'] = $currSes['SesID'];
        if((int)$upcand['ModeOfEntry'] == 0)$upcand['ModeOfEntry'] = "1";
        
        //insert
        $ins = $dbo->InsertID2("studentinfo_tb",$upcand);
        if(!is_numeric($ins))Error(28,"-".$ins);

        //4. create candidate details in accesscode
        //generate accesscode
        // $acccode = FormAC();
        $acccode = "myschool";
        $ins2 = $dbo->InsertID2("accesscode_tb",["RegNo"=>"","JambNo"=>$JambNo,"AccessCode"=>$acccode,"RegID"=>$upcand['RegID']]);
        if(!is_numeric($ins2)){
            $del = $dbo->Delete("studentinfo_tb","id=".$ins);
            Error(28,": Generating Accesscode Failed");
        }
        //5. Generate New RegNo and Update as required
        /* $autoreg = AutoGenRegNo($Param['RegNo'],$upcand['RegID']);
        if(!is_array($autoreg) &&  $autoreg != "##"){
            Error(29,$autoreg); 
        }
 
        $NewRegNo = is_array($autoreg)?$autoreg[0]:$Param['RegNo'];*/
        $NewRegNo = $JambNo;
        
        $mailparam = array_merge($Param,["ToAddress"=>$upcand['Email'],"AC"=>$acccode,"Optional"=>true],$upcand);
            $mailparam["RegNo"] = $NewRegNo ;
            $sch = GetSchool();
            $MailData = [
                "Logo"=>$dbo->Config["SubDir2"]."Files/".$sch['logo'],
                "SchoolName"=>$sch['Name'],
                "SchoolAbbr"=>$sch['Abbr'],
                "SurName"=>$upcand['SurName'],
                "FirstName"=>$upcand['FirstName'],
                "OtherNames"=>$upcand['OtherNames'],
                "RegNo"=>$JambNo,
                "AC"=>$acccode,
                "BrandLogo"=>$dbo->Config['Core2']."images/App/Images/eduporta.png"
            ];
            $dir = (isset($Param['Dir']) && trim($Param['Dir']) != "")?$Param['Dir']:"Apply/Account";
            $msg = '<div style="background-color: #eee; width:100%; height: auto; padding: 20px;font-family: \'Encode Sans Condensed\',\'Milo\',\'Open Sans\',sans-serif;">
            <div
                style="width:calc(100% - 30px); max-width:500px; min-height:400px; background-color:#fff; margin:auto; border-radius:10px; box-shadow:0 2px 5px 0 rgba(0,0,0,0.16),0 2px 10px 0 rgba(0,0,0,0.12);">
                <div
                    style="border-radius:10px 10px 0px 0px;min-height: 40px; width: 100%;background-color:rgb(15, 133, 35);box-shadow:0 2px 5px 0 rgba(0,0,0,0.16),0 2px 10px 0 rgba(0,0,0,0.12);">
                    <img style="height: 50px; display:inline-block; margin:10px 20px; vertical-align: middle"
                        src="{{Logo}}" /> <span
                        style="vertical-align:middle; display:inline-block; margin:10px 0px; font-size:1.3em; color:#fff">{{SchoolName}} <br/><span style="font-size:0.7em">Student Portal Account</span></span>
                </div>
    
                <div style="padding:20px">
                    <p>Congratulations <b>{{SurName}} {{FirstName}} {{OtherNames}}</b>,</p>
                       <p> Your {{SchoolAbbr}} Student Portal Account is created successfully</p>
                       <p>Your Username is</p>
                       <h1>{{RegNo}}</h1>
                       <p>Portal Access Code: <b style="color:red">{{AC}}</b></p>
                           
                        <p>Login to your {{SchoolAbbr}} Desk as follows:</p>
    
                       <ul>
    <!-- <li>Visit <a href="{{__Root__}}portals" target="_new">{{__Root__}}portals</a></li> -->
    <li>On the Home Screen Click on <b>Login</b></li>
    <!-- <li>On the <b>Login Page</b></li> -->
    <li>Supply your <br/>Username <b style="font-style: italic">{{RegNo}}</b></li>
    <li>Click the <b></b>Arrow Button</b> to verify your Username</li>
    <li>Supply your <br/>Access Code <b style="font-style: italic">{{AC}}</b></li>
    <li>Click the <b></b>Arrow Button</b> to Login</li>
                       </ul>
                </div>
            </div>
            <div style="width: auto; text-align: center; margin:30px">
                    <div class="bbwa-sponsors-img"><a href="#" style="display: inline-block;margin:2px 5px;vertical-align: middle;transition: filter 0.7s"><img style="min-height: 30px;max-height: 30px" src="{{Logo}}" /></a><a href="#" style="display: inline-block;margin:2px 5px;vertical-align: middle;transition: filter 0.7s"><img style="min-height: 20px;max-height: 20px" src="{{BrandLogo}}" /></a></div>
                    <div class="footer-note gen-text-shadow">&copy; {{SchoolAbbr}}</div>
                </div>
            </div>';
            if(count($MailData) > 0){
                foreach($MailData as $key=>$val){
                    $msg = str_replace("{{".$key."}}",$val,$msg);
                }
            }
             $sends = $dbo->SendMail($sch['OpEmail'],$upcand['Email'],$sch['Abbr']." Student Credentials",$msg,$sch['OpEmail'],$sch['OpEmailPassw'],$sch['OpEmailLive']=="FALSE"?false:true); 
          // $sends = SendMail($mailparam);
           if($sends !== true){
            //Error("CE","Sending Mail Failed");
         }

         //send sms
         //$sch = GetSchool();
                //Send Message
                 $sendmail = $dbo->SendSMS($sch['Abbr'],"Hello, ".$upcand['SurName']." ".$upcand['FirstName']. ", your Student Account is Created Successfully \n Reg. No: {$JambNo} \n Access Code: $acccode",$upcand['Phone'],"234",$sch['OpUName'],$sch['OpUPassw'],$sch['OpSMSLive']=="FALSE"?false:true); 
                

         $rd ="Slip.php?folder=regno=".$NewRegNo."&Form&paper=A4&orientation=P&MT=4&MB=30";
       // $canddet["RedirectURL"] = $rd;
        $rdata = "{Src:'{$__Root__}general/Slip.php?regno={$NewRegNo}&folder=Form&SubDir=".urlencode($dbo->Config['SubDir'])."',PayperType:'A4',Orientation:'P',MarginTop:4,MarginBottom:30}";
        $ardata = "{Src:'{$__Root__}general/Slip.php?RegNo=".urlencode($NewRegNo)."&folder=AcceptLetter&SubDir=".urlencode($dbo->Config['SubDir'])."',PayperType:'A4',Orientation:'P',MarginTop:4,MarginBottom:4}";

        //delete student entrance details if exist
        $delentrancedet = $dbo->Delete("pstudentinfo_tb","RegNo='".trim($dbo->SqlSafe($Param['RegNo']))."' OR JambNo='".trim($dbo->SqlSafe($Param['RegNo']))."'");
        //Error("CE",$Param['RegNo']);
    //$cand["ARedirectData"] = $ardata;
        return ["NextPageNum"=>4,"NRegNo"=>$NewRegNo,"NRedirectData"=>$rdata,"ARedirectData"=>$ardata];
    }else{
        return ["NextPageNum"=>2]; //not accepted
    }
   
}

//R024
function GetAllApplications($Param){
    //get all the group
  $appGroup = $dbo->Select("new_apply_group_tb","","Enable=1".$cnd);
  if(!is_array($appGroup))Error(4,": Reading Application Failed.");
  if($appGroup[1] < 1)Error(9," : Application Not Exist or Disabled");
  $applygrparr = [];
  $JointID = "";
  while($ind = $appGroup[0]->fetch_assoc()){
      $applygrpid = $ind["ID"];
      $JointID .= "_".$applygrpid;
      //get all apply details
      $app = $dbo->Select("new_apply_tb","ID as AID, Name as AppName, Descr as AppDescr, Logo as AppLogo","Enable=1 AND GroupID=".$applygrpid." ORDER BY MenuOrder");
      if(!is_array($app)){
        $ind["Applications"] = InternalError(4);
      }else{
        $ind["Applications"] = $dbo->FetchAll($app[0],MYSQLI_ASSOC);
      }
      $applygrparr[] = $ind;
      // $schooldet["Wallpapers"] = $dbo->FetchAll($schwp[0],MYSQLI_ASSOC);

  }
  return ["AppGroup"=>$applygrparr,"PAGEID"=>ltrim($JointID,"_")];
}

//R025
function ClearAllSessions(){
    $_SESSION = [];
    session_destroy();
    return 'true';
}

//R026
function GetSchoolSession($param = []){
    global $dbo;
    $ses = $dbo->SelectFirstRow("session_tb","","Enable=1 ORDER BY Current DESC, SesID DESC",MYSQLI_ASSOC);
    if(!is_array($ses)){
        Error(9," : No Academic Session Found");
    }
    return $ses;
}

function GetSessionName($SesID=0){
    global $dbo;
    $ses = $dbo->SelectFirstRow("session_tb","","SesID=$SesID",MYSQLI_ASSOC);
    if(!is_array($ses)){
        return "--";
    }
    return $ses['SesName'];
}
//Internal
function HasLogin(&$Param){
    session_start();
    if(!isset($Param['LoginName']) || trim($Param['LoginName']) == ""){
          if(isset($_SESSION['LoginName']) && trim($_SESSION['LoginName']) != ""){
            $Param['LoginName'] = $_SESSION['LoginName'];
          }else{
            Error(5);
          }
    }
}

//Internal
function GetStudentLevelSemesterWhenSchoolStart($RegNo){
    global $dbo;
    $lastLevel = $lastSem = 1;
    $sch = GetSchool("SchStartSes,SchStartSem");
            
    //use the school start ses to determin student lowest level
    $lastLevel = StudLevelSes($RegNo,$sch['SchStartSes']);
    //get the sem num
    $SchSemID = (int)$sch['SchStartSem'];
    if($SchSemID > 0){
       $semnum = $dbo->SelectFirstRow("semester_tb","Num","ID=$SchSemID");
       if(is_array($semnum) && (int)$semnum['Num'] > 0){
        $lastSem = $semnum['Num'];
       }
    }
    return [(int)$lastLevel,(int)$lastSem];
}
//R027
function GetStudentLevelSemester($Param){
    global $dbo;
    HasLogin($Param);

    $studDet = $dbo->SelectFirstRow("studentinfo_tb","OtherDet,StudyID","RegNo='".$dbo->SqlSafe($Param['LoginName'])."' OR JambNo='".$dbo->SqlSafe($Param['LoginName'])."'");
        if(!is_array($studDet))Error(8);

    //get the last course registration
    $lstcreg = $dbo->SelectFirstRow("coursereg_tb","Lvl,Sem","RegNo='".$dbo->SqlSafe($Param['LoginName'])."' ORDER BY SesID DESC, Lvl DESC, Sem DESC",MYSQLI_ASSOC);
    //Error(8,json_encode($lstcreg));
    $maxsem = 2;
    //get the maximum semester number
    $semma = $dbo->SelectFirstRow("semester_tb","count(ID)","Enable = 1");
    if(is_array($semma)){
        $maxsem = (int)$semma[0];
    }

    $lastLevel = 1; $lastSem = 1;
    if(is_array($lstcreg)){
        
        //last det
        $lastLevel = $lstcreg['Lvl'];
        $lastSem = (int)$lstcreg['Sem'];
        if(!isset($Param['Current']) || $Param['Current'] != TRUE){ //get next
            
            /* if($lastSem > 1)$lastLevel++;
        $lastSem = ($lastSem > 1)?1:$lastSem++; */
            if($lastSem >= $maxsem){
                $lastLevel++;
                $lastSem = 1;
            }else{
                $lastSem++;
            }
        }
        
    }else{
        
        //get the degree starting
        $degreelvlseen = false;
          $OtherDet = $studDet['OtherDet'];
          if(trim($OtherDet) != ""){
            $OtherDet = json_decode($OtherDet,true);
            if(isset($OtherDet['Degree'])){
              
                //get the degree details
                $degdet = $dbo->SelectFirstRow("school_degrees_tb","","ID=".$OtherDet['Degree']);
                if(is_array($degdet)){
                    $lastLevel = $degdet["StartLevel"];
                    $degreelvlseen = true;
                }
            }
          
        }
        
        if(!$degreelvlseen){
            
          list($lastLevel,$lastSem) = GetStudentLevelSemesterWhenSchoolStart($Param['LoginName']);
            
            //Error("CE",$lastLevel);
            

        }
    }
    //get the student current Level details
    $leveldet = $dbo->SelectFirstRow("schoollevel_tb","*,IF(Descr='',Name,Descr) as LevelName, ID as LID,Level as LevelID","Level=$lastLevel AND StudyID=".$studDet['StudyID'],MYSQLI_ASSOC);
    if(!is_array($leveldet))Error(30);
    //get the student semester det
    $semdet = $dbo->SelectFirstRow("semester_tb","*, IF(Descr='',Sem,Descr) as SemesterName, IF(Num=0,ID,Num) as SemID","Num > 0 && Num=$lastSem",MYSQLI_ASSOC);
    if(!is_array($semdet))Error(31);
//(Num > 0 && Num={$Param['SemesterID']}) || ID={$Param['SemesterID']}
    return array_merge($leveldet,$semdet);

}

//get the student stat - #R057
function GetStatistics($param){
    global $dbo;
    $lastlvl = 1; $lastsem = 1;
    //list()
    if(!isset($param['LevelID']) || !isset($param['SemID'])){
        
        $lastdet = GetStudentLevelSemester($param);
        $lastlvl = $lastdet['LevelID']; $lastsem = $lastdet['SemID'];
    }else{
        
        $lastlvl = $param['LevelID']; $lastsem = $param['SemID'];
    }
    $rtn = ["Course"=>"off","Payment"=>"off","Result"=>"off"];
   // return $rtn;
    //check if courseregistered
    $lstcreg = $dbo->SelectFirstRow("coursereg_tb","ID","RegNo='".$dbo->SqlSafe($param['LoginName'])."' AND Lvl=$lastlvl AND Sem=$lastsem LIMIT 1",MYSQLI_ASSOC);
    if(is_array($lstcreg))$rtn['Course'] = "on";

    $progID = GetStudentProgIDForPay($param['LoginName']);

    //check if payment
    $lstpay = $dbo->SelectFirstRow("payhistory_tb","ID","RegNo='".$dbo->SqlSafe($param['LoginName'])."' AND Lvl=$lastlvl AND Sem >= $lastsem AND SemPart > 1 AND ProgID=$progID LIMIT 1",MYSQLI_ASSOC);
    if(is_array($lstpay))$rtn['Payment'] = "on";

    //check if result
    $lstrst = $dbo->SelectFirstRow("result_tb","ID","RegNo='".$dbo->SqlSafe($param['LoginName'])."' AND Lvl=$lastlvl AND Sem = $lastsem LIMIT 1",MYSQLI_ASSOC);
    if(is_array($lstrst))$rtn['Result'] = "on";
    return $rtn;
}

//R039
function GetStudentCurrentLevelSemester($Param){
    $Param['Current'] = TRUE;
    return GetStudentLevelSemester($Param);
}


//#R029
function OlevelGrades($Param){
    global $dbo;
    $facs = $dbo->Select("olvlgrade_tb");
    //Error(4,$studyid);
    if(!is_array($facs))Error(4);
    return $dbo->FetchAll($facs[0],MYSQLI_ASSOC);
}

//#R030
function OlevelSubjects($Param){
    global $dbo;
    $facs = $dbo->Select("olvlsubj_tb");
    //Error(4,$studyid);
    if(!is_array($facs))Error(4);
    return $dbo->FetchAll($facs[0],MYSQLI_ASSOC);
}

//R033 - 
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//Snipet Used in Pages/Script/Course/loadstudreg.php in cportal
//So Any update done here should be done there
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
function GetStudentCourses($Param){
    
    global $dbo;
    //session_start();
    HasLogin($Param);

    //check if AutoCourseReg is disabled
    //get the course control detaisl
    $courseCntr = $dbo->SelectFirstRow("coursecontrol_tb");
    if($courseCntr['AutoRegStatus'] == "TRUE"){
        Error(40,'<br/><button class="bbwa-button w3-large" onclick="Application.Load({ApplyGID:3,AutoLoad:true,Home:true,Logout:false,Guest:true,OpenFrom:\'open-from-menu\'})" ><span class="mbri-credit-card"></span> &nbsp; Make Payment Now</button>');
    }

    $maxsem = 2;
    //get the maximum semester number
    $semma = $dbo->SelectFirstRow("semester_tb","count(ID)","Enable = 1");
    if(is_array($semma)){
        $maxsem = (int)$semma[0];
    }

    $studDet = $dbo->SelectFirstRow("studentinfo_tb","","RegNo='{$Param['LoginName']}' OR JambNo='{$Param['LoginName']}'");
            if(is_array($studDet)){
                $studDet['RegNo'] = (is_null($studDet['RegNo']) || trim($studDet['RegNo']) == "")?$studDet['JambNo']:$studDet['RegNo'];
    //get last course Registered
    $coursereg = $dbo->SelectFirstRow("coursereg_tb","*,Lvl as LevelID, Sem as SemesterID","RegNo='".$studDet['RegNo']."' OR RegNo='".$studDet['JambNo']."' ORDER BY Lvl DESC, Sem DESC",MYSQLI_ASSOC);
            if(!is_string($coursereg)){
                if(!is_array($coursereg)){
                    $coursereg = [];
                    list($LevelID,$SemesterID) = GetStudentLevelSemesterWhenSchoolStart($studDet['RegNo']);
                    //$coursereg['LevelID'] = 1;
                    //$coursereg['SemesterID'] = 0;
                }else{
                    $LevelID = $coursereg['LevelID'];
                    $SemesterID = $coursereg['SemesterID'];
                    
                    $SemesterID++;
                    
                if($SemesterID > $maxsem){
                    $SemesterID = 1;
                    $LevelID++;
                } 
                }
                
            //Error(4," - ".$LevelID." ; ".$SemesterID);
            //Error(4," - ".$LevelID." ; ".$SemesterID);
            //get the student progid
            
              $ProgID = $studDet['ProgID'];
              
              //check payment
              $PayDet = $dbo->SelectFirstRow("payhistory_tb","","(RegNo='".$studDet['RegNo']."' OR RegNo='".$studDet['JambNo']."') AND Lvl = {$LevelID} AND Sem >= $SemesterID AND SemPart > 0 AND ProgID=$ProgID AND PayID = {$courseCntr['PayID']}");
              $LevelName = GetStudentLevelName($LevelID,$studDet['StudyID']);
                  $semester = GetStudentSemesterName($SemesterID);
               if(is_array($PayDet)){
                   //get current session
                   $curses = GetSchoolSession();
                   $lvlses = $curses['SesID'];
                  //get the courses
                  $Courses = $dbo->Select("course_tb","","DeptID=".$ProgID." AND Lvl=$LevelID AND Sem=$SemesterID AND StartSesID <= $lvlses AND (EndSesID >= $lvlses OR EndSesID = 0) AND CourseStatus = 0");
                  if(!is_array($Courses))Error(32);
                  if($Courses[1] < 1)Error(33);
                  //get the max ch
                  $maxch = GetMaxCH($ProgID,$LevelID,$SemesterID);
                  $StudCourses = [];
                  $semclass = "semcourse";
                  $autoclass = "autoreg";
                  $llcclass = "llc";
                  //loop through each student courses and add classes as required
                  while($indcourse = $Courses[0]->fetch_assoc()){
                    $indcourse['Class'] = $semclass;
                    $indcourse['CourseCode'] = strtoupper($indcourse['CourseCode']);
                    $indcourse['Title'] = ucwords($indcourse['Title']);
                    //get the ch
                    $accCH += (int)$indcourse['CH'];
                    if($accCH <= $maxch){
                        $indcourse['Class'] .= " ".$autoclass;
                    }
                    $StudCourses[] = $indcourse;
                  }

                  //if lower level courses is enabled
                  $LLC = [];
                  if($courseCntr['LowerLevel'] == 'TRUE'){
                    $LCoursese = [];
                    $lCourses = $dbo->Select("course_tb","","DeptID=".$ProgID." AND Lvl<$LevelID AND Sem=$SemesterID  AND CourseStatus = 0 ORDER BY Lvl Desc");
                    if(!is_array($lCourses))Error(32);
                    if($lCourses[1] > 0){
                        $LevelSesArr = [];
                        while($lindcourse = $lCourses[0]->fetch_assoc()){
                            if(!isset($LevelSesArr[$lindcourse['Lvl']])){
                                //check if student register for course at the Lvl Sem
                                $courseregll = $dbo->SelectFirstRow("coursereg_tb","","RegNo='{$Param['LoginName']}' AND Lvl=".$lindcourse['Lvl']." AND Sem=".$lindcourse['Sem']);
                                if(is_array($courseregll)){ //if course registration exist for the lower level
                                //get the sesid
                                $LevelSesArr[$lindcourse['Lvl']] = (int)$courseregll["SesID"];
                                }else{
                                    //if the student does not register for the level which is abnormal
                                    //use the current session
                                    $LevelSesArr[$lindcourse['Lvl']] = $lvlses;  
                                }
                            }

                            //check if course not expired 
                            //StartSesID <= $lvlses AND (EndSesID >= $lvlses OR EndSesID = 0)
                            if((int)$lindcourse['StartSesID'] <= $LevelSesArr[$lindcourse['Lvl']] || ((int)$lindcourse['EndSesID'] >=  $LevelSesArr[$lindcourse['Lvl']] || (int)$lindcourse['EndSesID'] == 0)){
                                $lindcourse['Class'] = $llcclass;
                                $lindcourse['CourseCode'] = strtoupper($lindcourse['CourseCode']);
                                $lindcourse['Title'] = ucwords($lindcourse['Title']);
                            //get the ch
                           /*  $accCH += (int)$indcourse['CH'];
                            if($accCH <= $maxch){
                                $indcourse['Class'] .= " ".$autoclass;
                            } */
                            $LCoursese[] = $lindcourse;
                            }
                            
                            
                          }
                    }
                    if(count($LCoursese) > 0){
                        $LLC["Courses"] = $LCoursese;
                    }
                  }
                  
                  return ["SLC"=>["Courses"=>$StudCourses],"LLC"=>$LLC,"LevelName"=>$LevelName,"SemesterName"=>$semester,"LevelID"=>$LevelID,"SemesterID"=>$SemesterID,"ProgID"=>$studDet['ProgID'],"RegNo"=>$Param['LoginName'],"SemesterClass"=>$semclass,"AutoClass"=>$autoclass,"LLCClass"=>$llcclass];
               }else{
                   //Make the page auto reload incase user make payment
                   $Param['PageClass'] = "ReloadOnPaid";
                   $Param["ErrorImage"] = "images/pages/notpaid.png";
                   Error(13,' <br/> <button class="bbwa-button w3-large" onclick="((event)=>{Application.Load({ApplyGID:3,AutoLoad:true,Home:true,Logout:false,Guest:true,OpenFrom:\'open-from-menu\'});event.stopPropagation();})(event)" ><span class="mbri-credit-card"></span> &nbsp; Make Payment Now</button>',$Param);
                   /* Error(13,' <hr/>'.$LevelName.' / '.$semester.'<hr/><button class="bbwa-button w3-large" onclick="((event)=>{Application.Load({ApplyGID:3,AutoLoad:true,Home:true,Logout:false,Guest:true,OpenFrom:\'open-from-menu\'});event.stopPropagation();})(event)" ><span class="mbri-credit-card"></span> &nbsp; Make Payment Now</button>',$Param); */
               }
            
               // return $coursereg;
            }else{
                Error(4,": Reading Student Course Registration History Failed ".$coursereg);
            }
        }else{
            Error(4,": Reading Student Details Failed");
        }
}

//get the level by its is (Internal)
function GetStudentLevelName($LvlID,$StudyID = 5){
   global $dbo;
  //get the student current Level details
  $leveldet = $dbo->SelectFirstRow("schoollevel_tb","IF(Descr = '',Name,Descr) as LevelName","Level=$LvlID AND StudyID=".$StudyID,MYSQLI_ASSOC);
  if(!is_array($leveldet))return "--";
  //return $LvlID."  ".$StudyID;
  return $leveldet['LevelName'];
}

//get the level by its is (Internal)
function GetStudentSemesterName($SemID){
    global $dbo;
    //get the student semester det
    // $semdet = $dbo->SelectFirstRow("semester_tb","IF(Descr='',Sem,Descr) as SemesterName","(Num > 0 && Num=$SemID) || ID=$SemID",MYSQLI_ASSOC);
    $semdet = $dbo->SelectFirstRow("semester_tb","IF(Descr='',Sem,Descr) as SemesterName","Num=$SemID",MYSQLI_ASSOC);
    if(!is_array($semdet))return "Session";
    return $semdet['SemesterName'];
  }
  
  //R034
  function RegisterCourses($Param){
      global $dbo;global $__Root__;
      //Error(5," - ".json_encode($Param['toogleLcourses']);
      //check if a valid login student
      if(!isset($Param['RegNo']) || trim($Param['RegNo']) == "")Error(8);
    //check if valid course Registration details sent
    if(!isset($Param['CoursesReg']) || count($Param['CoursesReg']) < 1 || !isset($Param['LevelID']) || (int)$Param['LevelID'] < 1 || !isset($Param['SemesterID']) || (int)$Param['SemesterID'] < 1 || !isset($Param['ProgID']) || (int)$Param['ProgID'] < 1)Error(0);
    //get school session
    $getses = GetSchoolSession();
    $RegCoursesDet = [];
    $RegCourse = [];
    $totch = 0;
    //get all the selected courses
    foreach($Param['CoursesReg'] as $coursedet){
        if((int)$coursedet["state"] == 0 || (int)$coursedet["value"] == 0)continue;
        //get the course details
        $cdet = $dbo->SelectFirstRow("course_tb","","CourseID=".$coursedet["value"],MYSQLI_ASSOC);
        //if exist
        if(!is_array($cdet))continue;
        $RegCoursesDet[$coursedet["value"]] = $cdet;
        $RegCourse[] = $coursedet
        ["value"];
        $totch += $cdet['CH'];
    }

    //check if user select one or more coreses
    if(count($RegCourse) < 1)Error(36);

    //check lower level selection
    if((int)$Param['toogleLcourses'] == 1){
         //get all the selected courses
        foreach($Param['LCoursesReg'] as $coursedet){
            if((int)$coursedet["state"] == 0 || (int)$coursedet["value"] == 0)continue;
            //get the course details
            $cdet = $dbo->SelectFirstRow("course_tb","","CourseID=".$coursedet["value"],MYSQLI_ASSOC);
            //if exist
            if(!is_array($cdet))continue;
            $RegCoursesDet[$coursedet["value"]] = $cdet;
            $RegCourse[] = $coursedet
            ["value"];
            $totch += $cdet['CH'];
        }
    }

    //get the max ch (function from getinfo.php)
    $maxch = GetMaxCH($Param['ProgID'],$Param['LevelID'],$Param['SemesterID']);
    if($totch >  $maxch)Error(34," ($maxch)");

//check if already registered
$creg = $dbo->SelectFirstRow("coursereg_tb","ID","RegNo='".$dbo->SqlSafe($Param['RegNo'])."' AND Lvl=".$dbo->SqlSafe($Param['LevelID'])." AND Sem=".$dbo->SqlSafe($Param['SemesterID'])."");
if(is_array($creg)){
    
$Param['CourseRegID'] = $creg["ID"];
$ardata = "{Src:'{$__Root__}general/Slip.php?CourseRegID=".urlencode($creg["ID"])."&folder=Course&file=Slipi.php&SubDir=".urlencode($dbo->Config['SubDir'])."',PayperType:'A4',Orientation:'P',MarginTop:4,MarginBottom:4}";
$Param["PrintData"] = $ardata;
$Param["AutoReg"] = [];
return $Param;
}

    //register courses
    $reg = $dbo->InsertID2("coursereg_tb",["RegNo"=>$Param['RegNo'],"Lvl"=>$Param['LevelID'],"CoursesID"=>implode("~",$RegCourse),"SesID"=>$getses['SesID'],"Sem"=>$Param['SemesterID'],"RegDate"=>date('Y-m-d'),"MaxCH"=>$maxch,"CouresRegData"=>json_encode($RegCoursesDet),"TotCH"=>$totch]);
    //$reg = 1;
    if(is_numeric($reg)){
         
        //5. Generate New RegNo and Update as required
        $autoreg = AutoGenRegNo($Param['RegNo']);
        //Error(29," - ".$autoreg);
        //if error
         if(!is_array($autoreg) &&  $autoreg != "##"  &&  $autoreg != "####"){
            //remove course registered
            $del = $dbo->Delete("coursereg_tb","ID=".$reg);
            if($autoreg == "#")$autoreg = "Reading School Details Failed";
            if($autoreg == "###")$autoreg = "Reading Student Details Failed";
            if($autoreg == "#####")$autoreg = "Global Update Failed";
            Error(29, ", and Course Registration Reversed - ".$autoreg); 
        } 
        $AutoReg = [];
        //$autoreg = [$Param['RegNo']];
        if(is_array($autoreg)){
            $AutoReg = ["NewReg"=>$autoreg[0],"NRedirectData"=>"{Src:'{$__Root__}general/Slip.php?regno={$autoreg[0]}&folder=Form&SubDir=".urlencode($dbo->Config['SubDir'])."',PayperType:'A4',Orientation:'P',MarginTop:4,MarginBottom:30}"];
            $Param['RegNo'] = $autoreg[0];

            $studprog = $dbo->SelectFirstRow("studentinfo_tb","ProgID,SurName,FirstName,Phone","RegNo='{$Param['RegNo']}' OR JambNo='{$Param['RegNo']}'");
            if(is_array($studprog)){
                $sch = GetSchool();
                //Send Message
                $sendmail = $dbo->SendSMS($sch['Abbr'],"Hello, ".$studprog['SurName']." ".$studprog['FirstName']. ", your school Registration Number is {$Param['RegNo']}",$studprog['Phone'],"234",$sch['OpUName'],$sch['OpUPassw'],$sch['OpSMSLive']=="FALSE"?false:true);
                $rstdet = explode("|",$sendmail);
                if(strtolower($rstdet[0]) == "success"){
                //$sendmail = TRUE;
                }
            }

            
        }
        $Param['CourseRegID'] = $reg;
        $ardata = "{Src:'{$__Root__}general/Slip.php?CourseRegID=".urlencode($reg)."&folder=Course&file=Slipi.php&SubDir=".urlencode($dbo->Config['SubDir'])."',PayperType:'A4',Orientation:'P',MarginTop:4,MarginBottom:4}";
    $Param["PrintData"] = $ardata;
    //$Param['RegNo'] = 
    //$rdata = "{Src:'Slip.php?regno={$Param['RegNo']}&folder=Form',PayperType:'A4',Orientation:'P',MarginTop:4,MarginBottom:30}";
    $Param["AutoReg"] = $AutoReg;
    //Error(35,json_encode($Param));
        return $Param;
    }else{
        Error(35);
    }
  }

  //R035
function UndoCourseRegistration($Param){
    
    global $dbo;
    //session_start();
    HasLogin($Param);

    //conform required fields
    if(!isset($Param['CourseRegID']) || (int)$Param['CourseRegID'] == 0){
      Error(0);
    }

    //delete the courseReg Details
    $delc = $dbo->Delete("coursereg_tb","ID=".$Param['CourseRegID']." AND RegNo='".$Param['LoginName']."'");
    if(is_array($delc)){
        return [];
    }else{
        Error(37);
    }

}

//view course reg details - R036
function LoadCourseReg($Param){
    //Error(40," -- ".$Param['TestData']);
    //Error(4,json_encode($Param));
    global $dbo;global $__Root__;
    if(isset($Param['CourseRegID'])){ //if the course reg ID is set
        $totch = 0;
      //get it from database
      $courseReg = $dbo->SelectFirstRow("coursereg_tb","","ID=".$Param['CourseRegID'],MYSQLI_ASSOC);
      if(!is_array($courseReg))Error(4);
      $RtnArr = NULL;
      //get the courses registered
      $cregded = $courseReg['CouresRegData'];
      if(trim($cregded) != ""){//if it exist
         //convert to array
         $CoursesRegArr = json_decode($cregded,true);
         if(is_array($CoursesRegArr) && count($CoursesRegArr) > 0){ //if course registered details found
            $RtnArr = [];
            //loop trough the details and from the new return arr of courses
            foreach($CoursesRegArr as $CID=>$CDet){
                $CDet["CourseCode"] = strtoupper(trim($CDet["CourseCode"]));
                $CDet["Title"] = ucwords(trim($CDet["Title"]));

                $RtnArr[] = $CDet;
                $totch += (int)$CDet['CH'];
            }
         }
      }

      if(is_null($RtnArr)){ //if course detatils not found i.e registration is done on <v4
        $RtnArr = [];
         //get the courses registered string
         $CRegs = $courseReg['CoursesID'];
         if(trim($CRegs) != ""){
             //if the course reg details exist
             $CRegsArr = explode("~",$CRegs);
             if(count($CRegsArr) > 0){
                 foreach($CRegsArr as $CID){
                     //get the course details
                     $cdet = $dbo->SelectFirstRow('course_tb',"","CourseID=".$CID,MYSQLI_ASSOC);
                     if(is_array($cdet)){
                        $cdet["CourseCode"] = strtoupper(trim($cdet["CourseCode"]));
                        $cdet["Title"] = ucwords(trim($cdet["Title"]));
                         $RtnArr[]=$cdet;
                         $totch += (int)$cdet['CH'];
                     }
                 }
             }
         }

      }
     // $Param['CourseRegID'] = $reg;
        $ardata = "{Src:'{$__Root__}general/Slip.php?CourseRegID=".urlencode($Param['CourseRegID'])."&folder=Course&file=Slipi.php&SubDir=".urlencode($dbo->Config['SubDir'])."',PayperType:'A4',Orientation:'P',MarginTop:4,MarginBottom:4}";
      //Error(0,json_encode());
    //$Param["PrintData"] = $ardata;
      return ["TotalCH"=>$totch,"TotalCourses"=>count($RtnArr),"Courses"=>$RtnArr,"RegNo"=>$courseReg['RegNo'],"LevelID"=>$courseReg['Lvl'],"SemesterID"=>$courseReg['Sem'],"SessionID"=>$courseReg['SesID'],"PrintData"=>$ardata];
    }
    Error(0,' - Fetching Course Registration Details Failed');
}


//R037
function LoadCoursesRegHistory($Param){
    
    global $dbo;
    //session_start();
    HasLogin($Param);

    //get student details
    $studDet = $dbo->SelectFirstRow("studentinfo_tb","","RegNo='{$Param['LoginName']}' OR JambNo='{$Param['LoginName']}' LIMIT 1");
    if(!is_array($studDet))Error(8);
    
    //get all Courses Registered
    $coursesReg = $dbo->Select("coursereg_tb","","RegNo='{$studDet['RegNo']}' OR RegNo='{$studDet['JambNo']}' ORDER BY Lvl DESC, Sem DESC",MYSQLI_ASSOC);
    if(!is_array($coursesReg))Error(4);
    if($coursesReg[1] < 1)Error(38);
    
    //loop and form the history array
    $HistArr = [];
    //for speed and optimization do an internal cache
    $LevelName = [];
    $SemesterName = [];
    $SessionName = [];
    while($courseRegi = $coursesReg[0]->fetch_assoc()){
        //get the course RegDetails
        if(!isset($LevelName[$courseRegi['Lvl']])){ //if not in cache
          //get it
          $LevelName[$courseRegi['Lvl']] = GetStudentLevelName($courseRegi['Lvl'],$studDet['StudyID']);
        }
        if(!isset($SemesterName[$courseRegi['Sem']])){ //if not in cache
            //get it
            $SemesterName[$courseRegi['Sem']] = GetStudentSemesterName($courseRegi['Sem']);
          }
          if(!isset($SessionName[$courseRegi['SesID']])){ //if not in cache
            //get it
            $SessionName[$courseRegi['SesID']] = GetSessionName($courseRegi['SesID']);
          }

          $RegIDsArr = explode("~",$courseRegi['CoursesID']);
          $totcourse = count($RegIDsArr);

          //get the total ch
          $totch = $courseRegi['TotCH'];
          if($totch < 1 && $totcourse > 0){ //if courses exist and totch = 0, meaning it is <v4 registration
            //use the reg string
            foreach($RegIDsArr as $CID){
                $cdet = $dbo->SelectFirstRow('course_tb',"","CourseID=".$CID,MYSQLI_ASSOC);
                     if(is_array($cdet)){
                        $totch += $cdet['CH'];
                     }
            }
          }
          
  $RegDate = date('d, M Y', strtotime($courseRegi['RegDate']));
  if($RegDate == date('d, M Y'))$RegDate = "Today";
          $HistArr[] = ["SessionName"=>$SessionName[$courseRegi['SesID']],"LevelName"=>$LevelName[$courseRegi['Lvl']],"SemesterName"=>$SemesterName[$courseRegi['Sem']],"CourseRegID"=>$courseRegi['ID'],"RegDate"=>$RegDate,"TotalCourses"=>$totcourse,"TotalCH"=>$totch];

    }
    return $HistArr;
}


//R038
function LoadPaymentHistory($Param){
    global $dbo;global $__Root__;
    //session_start();
    HasLogin($Param);

$studDet = $dbo->SelectFirstRow("studentinfo_tb","","RegNo='{$Param['LoginName']}' OR JambNo='{$Param['LoginName']}' LIMIT 1");
    if(!is_array($studDet))Error(8);
    $Param['LoginName'] = (is_null($studDet['RegNo']) || trim($studDet['RegNo']) == "")?$studDet['JambNo']:$studDet['RegNo'];
    //get all student payment history
    $payhist = $dbo->Select("payhistory_tb p, item_tb i","p.*, i.ItemName","p.RegNo='{$Param['LoginName']}' AND p.PayID = i.ID and p.PayScope != 'w' ORDER BY PayDate DESC, Lvl DESC, ID DESC, Sem DESC, SemPart DESC",MYSQLI_ASSOC);
    if(!is_array($payhist))Error(4);
    if($payhist[1] < 1)Error(39);
    //payment history exist
    
    //loop and form the history array
    $HistArr = [];
    //for speed and optimization do an internal cache
    $LevelName = [];
    $SemesterName = [];
    $SessionName = [];
    $SemesterPartName = [1=>"PART",2=>"BALANCE",3=>"FULL"];
    while($paydeti = $payhist[0]->fetch_assoc()){
        //get the course RegDetails
        if(!isset($LevelName[$paydeti['Lvl']])){ //if not in cache
          //get it
          $LevelName[$paydeti['Lvl']] = GetStudentLevelName($paydeti['Lvl'],$studDet['StudyID']);
        }
        if(!isset($SemesterName[$paydeti['Sem']])){ //if not in cache
            //get it
            $SemesterName[$paydeti['Sem']] = GetStudentSemesterName($paydeti['Sem']);
          }
          if(!isset($SessionName[$paydeti['SesID']])){ //if not in cache
            //get it
            $SessionName[$paydeti['Ses']] = GetSessionName($paydeti['Ses']);
          }

          /* {"Name":"Yomi Aniedi Ekanem","ProgID":"16","ProgName":"Agricultural Engineering ","DeptID":"16","DeptName":"Agricultural Engineering","FacID":"2","FacName":"Vocational & Technical Education","StartSes":"10","ModeOfEntry":"1","StudyID":"5","RegID":"1","PayName":"AKSCOE ACCEPTANCE FEE"} */
          //get the school settings
          $sch = GetSchool("SchStrucContr");
          $schstuc = json_decode($sch['SchStrucContr'],true);
          $dispst = true;
          $disprog = true;
          /* {"StudyID":{"SilentMode":false,"Name":"School"},"FacID":{"SilentMode":false,"Name":"Faculty"},"DeptID":{"SilentMode":false,"Name":"Department"},"ProgID":{"SilentMode":false,"Name":"Programme"},"SchID":{"Name":"School Group"},"FacGrpID":{"Name":"Faculty Group"},"ClassID":{"Name":"Class Group","SilentMode":false}} */
          if(is_array($schstuc)){// if it is valid
            $dispst = !$schstuc['StudyID']['SilentMode'];
            $disprog = !$schstuc['ProgID']['SilentMode'];
          }

          $payinfo = json_decode($paydeti['Info'],true);
          $studschooldet = [];
          if(is_array($payinfo) && $dispst){
              if(isset($payinfo['StudyName'])){
                $studschooldet[] = $payinfo['StudyName'];
              }

              if(isset($payinfo['ProgName']) && $disprog){
                $studschooldet[] =  $payinfo['ProgName'];
            }
            
          }
          $studschdetstr = implode(" / ",$studschooldet);

          $PayDate = date('d, M Y', strtotime($paydeti['PayDate']));
          ;
          //$paydis = $paydate->format();
         $HistArr[] = ["SessionName"=>$SessionName[$paydeti['Ses']],"LevelName"=>$LevelName[$paydeti['Lvl']],"SemesterName"=>$SemesterName[$paydeti['Sem']],"SemesterPartName"=>$SemesterPartName[$paydeti['SemPart']], "Amt"=>number_format($paydeti['Amt'],2),"PayRef"=>$paydeti['TransID'],"ItemName"=>$paydeti['ItemName'],"PayID"=>$paydeti['PayID'],"PayDate"=>$PayDate, "PaySchDet"=>$studschdetstr,"Redirect"=>$__Root__."general/Slip.php?folder=Payment&ItemNo=".$paydeti['TransID']."&paper=A4&orientation=P&MT=4&MB=30&SubDir=".urlencode($dbo->Config['SubDir'])];

    }
    return $HistArr;
}

//R040
function WalletDetails($Param){
    HasLogin($Param);
 global $dbo;
 $walc = $dbo->SelectFirstRow("walletcontrol_tb w, item_tb i","","w.PayID=i.ID LIMIT 1");
 if(!is_array($walc))Error(41);
 $amts = trim($walc['Amts']);
 if($amts == "")Error(41);
 $amtsobj = json_decode($amts,true);
 if(is_null($amtsobj))Error(41);
 //get the control details
 $cntrdet = $dbo->SelectFirstRow($walc['ControlTable'],"","ID={$walc['ControlTableID']} LIMIT 1");
 if(!is_array($cntrdet))Error(41);
 //check status
 if($cntrdet['Status'] == "CLOSED")Error(42);
 $bal = '0.00';
 //get the student last balance
 $lasttrans = $dbo->SelectFirstRow("wallet_tb","","RegNo='".$dbo->SqlSafe($Param['LoginName'])."' ORDER BY ID DESC LIMIT 1");
 if(is_array($lasttrans)){ //if transaction exist
    $bal = number_format($lasttrans['Balance'],2);
 }
 $rtn = [];
 $Curency = $dbo->SelectFirstRow("currency_tb");
 //check if other exist
 //$order = $dbo->SelectFirstRow("order_tb","","RegNo='".$dbo->SqlSafe($Param['LoginName'])."' ORDER BY ID DESC LIMIT 1");
 foreach($amtsobj as $indamt){
    $rtn[] = ["FAmount"=>number_format($indamt,2),"Amount"=>$indamt,"Descr"=>$Curency['Abbr'],"Currency"=>$Curency['Abbr']];
 }

 return ["PreAmount"=>$rtn,"PayID"=>$walc['PayID'],"Balance"=>$bal];
}


//R041
function LoadResultHistory($Param){
global $dbo;
    HasLogin($Param);

//get student details
$studDet = $dbo->SelectFirstRow("studentinfo_tb","","RegNo='{$Param['LoginName']}' OR JambNo='{$Param['LoginName']}' LIMIT 1");
if(!is_array($studDet))Error(8);
   
//get all Student Result
$studrst = $dbo->Select("result_tb","","RegNo='{$studDet['RegNo']}' OR RegNo='{$studDet['JambNo']}' ORDER BY Lvl DESC, Sem DESC, GroupID DESC",MYSQLI_ASSOC);

if(!is_array($studrst))Error(4, " : Reading Reading Result");
if($studrst[1] < 1)Error(43);


//loop and form the history array
$HistArr = [];
//for speed and optimization do an internal cache
$LevelName = [];
$SemesterName = [];
$SessionName = [];
$Found = [];
while($studRsti = $studrst[0]->fetch_assoc()){
    //get the course RegDetails
    if(!isset($LevelName[$studRsti['Lvl']])){ //if not in cache
      //get it
      $LevelName[$studRsti['Lvl']] = GetStudentLevelName($studRsti['Lvl'],$studDet['StudyID']);
    }
    if(!isset($SemesterName[$studRsti['Sem']])){ //if not in cache
        //get it
        $SemesterName[$studRsti['Sem']] = GetStudentSemesterName($studRsti['Sem']);
      }
      if(!isset($SessionName[$studRsti['SesID']])){ //if not in cache
        //get it
        $SessionName[$studRsti['SesID']] = GetSessionName($studRsti['SesID']);
      }

if(isset($Found[$studRsti['Lvl']."_".$studRsti['Sem']."_".$studRsti['SesID']]))continue;
$Found[$studRsti['Lvl']."_".$studRsti['Sem']."_".$studRsti['SesID']] = true;
    $TRC = (int)$studRsti['TRC'];
if($TRC < 1){
    if(trim($studRsti['Rst']) == "")continue; //if noresult upoaded yet
  $TRC = count(explode("&",$studRsti['Rst']));
}
      
$RegDate = date('d, M Y', strtotime($studRsti['RstDate']));
if($RegDate == date('d, M Y'))$RegDate = "Today";
      $HistArr[] = ["SessionName"=>$SessionName[$studRsti['SesID']],"LevelName"=>$LevelName[$studRsti['Lvl']],"SemesterName"=>$SemesterName[$studRsti['Sem']],"ResultID"=>$studRsti['ID'],"ResultDate"=>$RegDate,"TRC"=>$TRC];

}
return $HistArr;

}




//R042
function LoadResultDetails($Param){
global $dbo;global $__Root__;
    HasLogin($Param);
    $studDet = $dbo->SelectFirstRow("studentinfo_tb","RegNo,JambNo,ProgID,ClassID,StartSes","RegNo='{$Param['LoginName']}' OR JambNo='{$Param['LoginName']}' LIMIT 1",MYSQLI_ASSOC);
          if(!is_array($studDet))Error(8);
    //Error(0,$Param['ResultID']);
    $rsult = $dbo->SelectFirstRow("result_tb","","(RegNo='".$dbo->SqlSafe($studDet['RegNo'])."' OR RegNo='".$dbo->SqlSafe($studDet['JambNo'])."') and ID = {$Param['ResultID']} LIMIT 1",MYSQLI_ASSOC);
     if(!is_array($rsult))Error(44); //invalid result

     //get the result settings
     $rstset = $dbo -> SelectFirstRow("resultinfo_tb","","ID = (select GrdStrucID from school_tb limit 1)");
     if(!is_array($rstset))Error(45); //invalid result setting

     $PrePayStatus = (int)$rstset['PrePayStatus'];
     if($PrePayStatus == 1){//if to verify Payment
        
        list($studschlvl,$studschsem) = GetStudentLevelSemesterWhenSchoolStart($Param['LoginName']);
        //Error("CE",$studschlvl."-".$studschsem."-".$Param['LoginName']);
           //if result lvl is less than the student level wen school start, or the result level is same and the result sem is less than wen school sem start: implies that the result exist before the system start processing i.e should be made visible 
           if($studschlvl < (int)$rsult['Lvl'] || ($studschlvl == (int)$rsult['Lvl'] && $studschsem <= $rsult['Sem'])){
        $PayID = (int)$rstset['PrePayID'];
        $PrePayBases = (int)$rstset['PrePayBases'];
                //get the payment details
                $PayDet = $dbo -> SelectFirstRow("item_tb","","ID = $PayID LIMIT 1");
                if(!is_array($PayDet))Error(46); //invalid payment type 

                if($PrePayBases < 2){ //if full payment required
                    //full payment
                    $semcond = "AND SemPart > 1";
                }else{  //if part payment
                    $semcond = "AND SemPart >= 1";
                }
                
                //get the order details
                $OrderDet = $dbo -> SelectFirstRow("order_tb","","ItemID = $PayID AND (RegNo='".$dbo->SqlSafe($studDet['RegNo'])."' OR RegNo='".$dbo->SqlSafe($studDet['JambNo'])."') AND Lvl = {$rsult['Lvl']} AND (Sem = {$rsult['Sem']} || Sem = (SELECT COUNT(ID) + 1 FROM semester_tb WHERE Enable = 1)) $semcond AND ProgID=".$studDet['ProgID']." ORDER BY SemPart DESC, ID DESC LIMIT 1");
                
                $err = '<br />'.$PayDet['ItemName'].'<br /> Use the <span class="appcolor">Payment</span> <i class="fas fa-chevron-right"></i> <span class="appcolor">School</span>  Module to make Payment';
                //check if order exist
                // if(!is_array($OrderDet))Error(13,$err );
                $haspaid = false;
               // Error("CE","ItemID = $PayID AND (RegNo='".$dbo->SqlSafe($studDet['RegNo'])."' OR RegNo='".$dbo->SqlSafe($studDet['JambNo'])."') AND Lvl = {$rsult['Lvl']} AND (Sem = {$rsult['Sem']} || Sem = (SELECT COUNT(ID) + 1 FROM semester_tb WHERE Enable = 1)) $semcond AND ProgID=".$studDet['ProgID']." ORDER BY SemPart DESC LIMIT 1");
                if(!is_array($OrderDet))Error(13,$err);
                    
                    //get the ref
                    $Ref = $OrderDet['TransNum'];
                    //verify payment
                    $paid = HasPaidRef($Ref,$OrderDet);
                    if($paid[0] != 1)Error(13,$err);
                /* else{
                    
                } */
                if(!$haspaid){
                    //check if the result is below the school start details
                    
                    
                }
           }
        
      }
    
        //get the uploaded results
        $Rst  = trim($rsult['Rst']);
        if($Rst == "")Error(43); //no result
        $RstInfo = trim($rsult['RstInfo']);
        $RstInfoObj = [];
        if($RstInfo == ""){
            
            //get the grading structure and others
            $SemCourses = GetCourses($studDet['ProgID'],$rsult['Lvl'], $rsult['Sem']);
            //get grading details
       //$grdstr = $dbo -> SelectFirstRow("resultinfo_tb","","ID = (select GrdStrucID from school_tb limit 1)");
        // $grdstr = is_array($grdstr)?$grdstr[1]:"";
        // $schgrdstr = GetGradeDetAll();
        }else{
            $RstInfoObj = json_decode($RstInfo,true);
        }

        //get results
        $RstArr = $dbo->DataArray($Rst);
        $RstDet = [];
        $posbycourse = false;
        $PortalResultDisplay = [];
        if(!is_null($rstset['PortalResultDisplay'])){
            $PortalResultDisplay = json_decode($rstset['PortalResultDisplay'],true);
            if(isset($PortalResultDisplay['POSCourse']) && (int)$PortalResultDisplay['POSCourse'] == 1){
                $AllClassStudTotScoreByCourse = GetStudentClassResultsAllCourse($rsult,$studDet,true);
                $posbycourse = true;
            }
        }
        //loop through individual result
        foreach ($RstArr as $CID => $IndRst) {
            if($posbycourse){
               $courserstdet = StudentPositionBySubjectinClass($Param['LoginName'],$CID,$AllClassStudTotScoreByCourse);
              $CAVG = $courserstdet['AVG'];
              $subjposord = $courserstdet['POS']; 
            }
            
            $CDet = [];
            //check if course details exist in $RstInfo
            if(isset($RstInfoObj[$CID])){
                $CDet = $RstInfoObj[$CID];
            }else{
                $CDet = isset($SemCourses[$CID])?$SemCourses[$CID]:CourseDetails($CID);       
            }

            $IndRstArr = explode("|",$IndRst);
            $Scores = $IndRstArr[0];
            $MaxScores = $IndRstArr[1];
            $Point = $IndRstArr[2];
            $Grade = $IndRstArr[3];
            $GradeDescr = $IndRstArr[4];
            $passed = $IndRstArr[5]; //1-PASS, 0-FAILED
            $CH = $IndRstArr[6];
            $GradePoint = $IndRstArr[7];
            $MaxScoresArr = [];
            //check if <v4 structure
            $commexist = strpos($Scores,",");
            if($commexist !== FALSE){ //=>v4
                //get ind scores
                $ScoresArr = explode(",",$Scores);
                $MaxScoresArr = explode(",",$MaxScores);
            }else{
                $ScoresArr = [$Scores,$MaxScores];//CA and Exam
            }

            $tot = array_sum($ScoresArr);
            $rstatus = (int)$passed <= 0?"FAILED":"PASSED";

            //check if course is approved
            $chkappr = $dbo->SelectFirstRow("resultapprove_tb","","Ses= {$rsult['SesID']} AND CourseID=$CID");
           // if(!is_array($chkappr))Error(45," (".$CDet['Title']." - ".$CDet['CourseCode'].")");
            if((!is_array($chkappr) || $chkappr['Status'] == "FALSE") && (int)$rstset['ViewOnApprove'] > 0){
               $dett = !is_array($chkappr)?"APPROVAL ERROR":"NOT APPROVED";
                $RstDet[] = ["CourseCode"=>PlainText($CDet['CourseCode']),"CourseCH"=>$CH,"CourseTitle"=>PlainText($CDet['Title']),"Total"=>"-","GradePoint"=>"-","Status"=>$dett,"Details"=>[],"Grade"=>"-","CourseID"=>$CID];
            }else{
                $Details = [];
                $StucArr = !is_null($chkappr['ScoreStruc'])?json_decode($chkappr['ScoreStruc'],true):["Assessment","Examination"];
                $MaxStucArr = !is_null($chkappr['ScoreStrucMax'])?json_decode($chkappr['ScoreStrucMax'],true):[];
                for($as=0; $as<count($StucArr); $as++){
                    $rScore = isset($ScoresArr[$as])?$ScoresArr[$as]:0;
                    $Details[] = ["StrucName"=>$StucArr[$as],"StrucScore"=>$rScore,"StrucMax"=>isset($MaxStucArr[$as])?("/".$MaxStucArr[$as]):"","StrucDescr"=>""];
                }
                $Details[] = ["StrucName"=>"TOTAL","StrucScore"=>$tot,"StrucMax"=>count($MaxStucArr)>0?("/".array_sum($MaxStucArr)):"","StrucDescr"=>""];
                $Details[] = ["StrucName"=>"GRADE","StrucScore"=>$GradeDescr,"StrucMax"=>" (".$Grade.")","StrucDescr"=>$GradeDescr];
                if($posbycourse){
                    $Details[] = ["StrucName"=>"AVG","StrucScore"=>$CAVG,"StrucMax"=>"","StrucDescr"=>""];
                    $Details[] = ["StrucName"=>"POSITION","StrucScore"=>$subjposord,"StrucMax"=>"","StrucDescr"=>""];
                }
                
                
                $RstDet[] = ["CourseCode"=>PlainText($CDet['CourseCode']),"CourseCH"=>$CH,"CourseTitle"=>PlainText($CDet['Title']),"Total"=>$tot,"GradePoint"=>$GradePoint,"Status"=>$rstatus,"Details"=>$Details,"Grade"=>$Grade,"CourseID"=>$CID];
            }
        }
       unset($rsult['RstInfo']);
       unset($rsult['Rst']);
       unset($rsult['COPRule']);
       unset($rsult['COPDetails']);
       unset($rsult['Rept']);
       unset($rsult['Outst']);
       //form the display result array
       $DisRest = [];
       if(count($PortalResultDisplay) > 0){
         $PortalResultDisplay = json_decode($rstset['PortalResultDisplay'],true);
         //check if position is visible
         $rsult['POS'] = "--";
         //check if position is visible
	//$rstarr['POS'] = "--";
	if($PortalResultDisplay['POS'] == 1){
		$rsult['POS'] = GetStudentResultPosition($rsult,$studDet);
		
		//$rstarr['POS'] = FormatPos($rstarr['POS']);
	}
	if($PortalResultDisplay['POSClass'] == 1){
		$rsult['POSClass'] = GetStudentResultPosition($rsult,$studDet,true);
		//$rstarr['POSClass'] = FormatPos($rstarr['POSClass']);
	}

	if($PortalResultDisplay['AVGClass'] == 1){
		$classrstdet = GetStudentOverallClassResultDetails($rsult,$studDet,true);
  $classavg =round($classrstdet[2]/$classrstdet[0],2);
  $rsult['AVGClass'] = $classavg ;
	}
         $DescrArr = ["GPA"=>["GPA","GPA"],"CGPA"=>["CGPA","CGPA"],"TOT"=>["Total","OTS"],"AVG"=>["Average","OAS"],"AVGClass"=>["Class Average","AVGClass"],"POS"=>["Level Position","POS"],"POSClass"=>["Class Position","POSClass"],"COP"=>["Grade","COP"]];
         foreach($PortalResultDisplay as $Dis=>$stat){
             if($stat != 0 && isset($DescrArr[$Dis])){
                 if($stat == 1){
                    $DisRest[] = ["Title"=>$DescrArr[$Dis][0],"Value"=>$rsult[$DescrArr[$Dis][1]]]; 
                 }else{
                    $DisRest[] = ["Title"=>$DescrArr[$Dis][0],"Value"=>"--"]; 
                 }
             }
         }

       }

       $ardata = "{Src:'{$__Root__}general/Slip.php?RID=".$rsult['ID']."&folder=Result&file=Slipi.php&SubDir=".urlencode($dbo->Config['SubDir'])."',PayperType:'A4',Orientation:'P',MarginTop:4,MarginBottom:4}";
    //$Param["PrintData"] = $ardata;


        return array_merge($rsult,["ResultDetails"=>$RstDet,"Overal"=>$DisRest,"PrintData"=>$ardata]);
        //return ["GPA"=>1.7];
            
       // Error(0,json_encode($rsult));
    
}

//Internal - get the next time verification code is to be sent (needed for phone verification) - manage waist of sms unit
function NextSendTime($param){
    $str = "";
   // $Use = (int)$otpdet['OtpUse'];
       $Tries = (int)$param['Counter'];
       //if already used, generate new one
      // $otp = $Use > 0?mt_rand(100000,999999):$otpdet['OTP'];
       $Tries = $Tries < 1?1:$Tries;
//$Tries = $Use > 0?0:$Tries; //if already used don't let user wait
       $now = new DateTime();
       $sendwait = ($Tries * $Tries) * 3 * 60; //in seconds
       $lastSend = new DateTime($param['VDate']);
       $diffInSeconds = $now->getTimestamp() - $lastSend->getTimestamp();
       
       //if user need to wait
       if($diffInSeconds < $sendwait){
        $wait = $sendwait - $diffInSeconds; 
        $wait = gmdate("G:i:s", $wait);
        $waitarr = explode(":",$wait);
        
        if((int)$waitarr[0] > 0){
            $plur = (int)$waitarr[0] > 1?"s":"";
            $str = $waitarr[0]." hour".$plur." ";
        }if((int)$waitarr[1] > 0){
         $plur = (int)$waitarr[1] > 1?"s":"";
         $str .= (int)$waitarr[1]." minite".$plur." ";
     }if((int)$waitarr[2] > 0){
         $plur = (int)$waitarr[2] > 1?"s":"";
         $str .= (int)$waitarr[2]." second".$plur;
     }
          
       }
       return $str;
}

//R043
function SendVerCode($Param){
    //Error(0,json_encode($Param));
    global $dbo;
    $entrancedet = Entrance($Param);
    // $isemail = (isset($Param['vertype']) && strtolower(trim($Param['vertype'])) == "email")?TRUE:FALSE;
    
    //Error(0,json_encode($dbo->Config));
    //Error(0,json_encode(array_merge($Param,$dbo->Config)));
    //check if the email sent
    if(isset($Param['RegNo_Appl']) && trim($Param['RegNo_Appl']) != ""){
       
        $regnotype = explode("@",$Param['RegNo_Appl']);
        $isemail = count($regnotype) > 1?TRUE:FALSE;
        $isemailstr = ($isemail)?"Email Address":"Phone Number";
        $dbkey = ($isemail)?"Email":"Phone";
        
       // $resendmsg = (isset($Param['Resend']) && $Param['Resend'] == true)?["__Alert__"=>"New Verification Code Sent Successfully"]:[];
        //get url part
        $emalarr = $isemail?$regnotype:["",""];
        //check if the email already exist for an applicant
        $appldet = $dbo->SelectFirstRow("pstudentinfo_tb","","RegNo='".$dbo->SqlSafe($Param['RegNo_Appl'])."' OR JambNo='".$dbo->SqlSafe($Param['RegNo_Appl'])."'");
        if(is_array($appldet)){
            
            //get the level
            $PageNum = $appldet['RegLevel'];
            return ["PageNum"=>$PageNum,"RegNo_Appl"=>$Param['RegNo_Appl'],"MailBox"=>$emalarr[1],"vertype"=>$isemail?"email":"phone","VerTypeStr"=>$isemailstr];
        }else{
            
            //valid email
            //generate validation number and send it to the mail
            $VeriNum = mt_rand(100000,999999);
            //check if already exist in applicantver_tb
            $everdet = $dbo->SelectFirstRow("applicantver_tb","","Email='".$dbo->SqlSafe($Param['RegNo_Appl'])."' OR Phone='".$dbo->SqlSafe($Param['RegNo_Appl'])."'");
            $VerID = 0;
            $totsend = 0;
            if(is_array($everdet)){ //if exist
                $totsend = (int)$everdet['Counter'];
                if(isset($Param['Resend']) && $Param['Resend'] == true){
                    //update counter
                    if(!$isemail){ //if phone verification
                        $waitstr = NextSendTime($everdet); //get the next allowed resend time
                        if(trim($waitstr) != ""){
                            Error("CE"," Resend not allowed<br/>kindly wait for the next <strong class='appcolor'>".$waitstr."</strong>",[],"clock");
                        }
                    }
                //update it
                $upd = $dbo->Update("applicantver_tb",["Pin"=>$VeriNum,"VDate"=>date("Y-m-d h:i:s"),"Counter"=>($totsend + 1)],"ID=".$everdet['ID']);
                if(!is_array($upd)){
                    Error(48);
                }
                }else{ //if not a resend
                    $VeriNum = $everdet['Pin'];
                }
                $VerID = $everdet['ID'];
               
            }else{
                
                $ins = $dbo->InsertID("applicantver_tb",["$dbkey"=>$Param['RegNo_Appl'],"Pin"=>$VeriNum,"VDate"=>date("Y-m-d h:i:s")]);
                
                if(!is_numeric($ins)){
                    Error(48); 
                }
                $VerID = $ins;
            }
            
            //get school detatils
            $sch = GetSchool();
           // Error(0,$sch['logo']);
           if(($isemail && (is_null($sch['OpEmail']) || is_null($sch['OpEmailPassw']))) || (!$isemail && (is_null($sch['OpUName']) || is_null($sch['OpUPassw'])))){
               Error(49);
           }
           
           //get the mail markup
           //$mkupurl = "../../Pages/";
           if($isemail){ //if to send email
              $lookup = "../../Pages/";
           if(file_exists("../../../../".$dbo->Config["SubDir"]."Pages/".$Param['Dir']."/VerCode.html")){
               $lookup = "../../../../".$dbo->Config["SubDir"]."Pages/";
           }
     $msg = "Verification Code: <b>$VeriNum</b>";
           if(file_exists($lookup.$Param['Dir']."/VerCode.html")){
              $msg = file_get_contents($lookup.$Param['Dir']."/VerCode.html");
              if($msg != ""){
                  $msg = str_replace(["{{Logo}}","{{SchoolName}}","{{ApplEmail}}","{{VerPin}}","{{Abbr}}","{{SubDir}}","{{Core}}","{{Dir}}"],[$dbo->Config["SubDir2"]."Files/".$sch['logo'],$sch['Name'],$Param['RegNo_Appl'],$VeriNum,$sch['Abbr'],$dbo->Config['SubDir2'],$dbo->Config['Core2'],$Param['Dir']],$msg);
              }
           }
         //return ["Mail"=>$msg];
            //send the verification number to the applicant mail
            $sendmail = $dbo->SendMail($sch['OpEmail'],$Param['RegNo_Appl'],$sch['Abbr']." Applicant Verification",$msg,$sch['OpEmail'],$sch['OpEmailPassw'],$sch['OpEmailLive']=="FALSE"?false:true); 
        // Error("CE","jkjj");

           }else{
               //if is sms verification
            $sendmail = $dbo->SendSMS($sch['Abbr'],$VeriNum,$Param['RegNo_Appl'],"234",$sch['OpUName'],$sch['OpUPassw'],$sch['OpSMSLive']=="FALSE"?false:true);
            $rstdet = explode("|",$sendmail);
            if(strtolower($rstdet[0]) == "success"){
             $sendmail = TRUE;
            }
           }
           
           // Error(0,$sendmail);
            //return ["Mail"=>$msg];
            if($sendmail !== TRUE){
                Error(50," : ".$sendmail);
            }
            if(isset($Param['Resend']) && $Param['Resend'] == true)Error("CE","New Verification Code Sent Successfully",[],"envelope");
            
            return ["RegNo_Appl"=>$Param['RegNo_Appl'],"MailBox"=>$emalarr[1],"vertype"=>$isemail?"email":"phone","VerTypeStr"=>$isemailstr];

//add the applicant
            //Error(0," - ".$VeriNum);
        }
        
    }else if(isset($Param['Appl_Phone'])){
        Error(0," Phone Verification");
    }else{
        Error(11);
    }
}

//R044
function VerifyApplicantEmail($Param){
    global $dbo;
    $entrancedet = Entrance($Param);
    if(!isset($Param['VerCode']))Error(0);
    if(trim($Param['VerCode']) == "" || (int)$Param['VerCode'] == 0)Error(51);
    if(!isset($Param['RegNo_Appl']) || trim($Param['RegNo_Appl']) == ""){
        // return ["PageNum"=>1,"__Alert__"=>"Sorry, we could not Identify you. Enter your Email Address and Try Again"];
        return RedirectTo(1,"Sorry, we could not Identify you. Try Again");
    }
    $regarr = explode("@",$Param['RegNo']);
    if(count($regarr) > 1){ //if the type of regno is email
      $isphone = FALSE;
      $regtype = "Email";
    }else{
        $isphone = TRUE;
        $regtype = "Phone";
    }
    //get the PIN of the user
    $appldet = $dbo->SelectFirstRow("applicantver_tb","","Email='".$dbo->SqlSafe($Param['RegNo_Appl'])."' OR Phone='".$dbo->SqlSafe($Param['RegNo_Appl'])."'");
    if(!is_array($appldet)){
        //return ["PageNum"=>1,"__Alert__"=>"Invalid Email Address, Enter your registered Email and Continue"];
        return RedirectTo(1,"Invalid Email Address, Enter your registered $regtype and Continue");
    }
    if($Param['VerCode'] != $appldet['Pin'])Error(51);
    //Error("CE",json_encode($Param));
    if(!isset($Param['ToPageNum']))$Param['ToPageNum'] = 3;//if the next page not sent set to 3
    //create the applicant registration entering
    //check if applicant entering already register
    $appldet = $dbo->SelectFirstRow("pstudentinfo_tb","","RegNo='".$dbo->SqlSafe($Param['RegNo_Appl'])."' OR JambNo='".$dbo->SqlSafe($Param['RegNo_Appl'])."'");
        if(!is_array($appldet)){
            $insertdata = ["RegNo"=>$Param['RegNo_Appl'],"RegLevel"=>$Param['ToPageNum'],"OtherDet"=>json_encode(["EntranceID"=>$entrancedet['ID']])];
            if($isphone){
                $insertdata["Phone"] =  $Param['RegNo_Appl'];
            }else{
                $insertdata["Email"] =  $Param['RegNo_Appl'];
            }
            $ins = $dbo->InsertID2("pstudentinfo_tb",$insertdata);
            if(!is_numeric($ins)){
                Error(48,"-".$ins); 
            }
        }else{ //if entering exixt check if not same Entrance ID, update it
            $otherdet = !is_null($appldet['OtherDet']) && trim($appldet['OtherDet']) != ""?json_decode($appldet['OtherDet'],true):[];
            if(!isset($otherdet['EntranceID']) || $otherdet['EntranceID'] != $entrancedet['ID']){
                //update it
                $otherdet['EntranceID'] = $entrancedet['ID'];
                $updcand = $dbo->Update("pstudentinfo_tb",['OtherDet'=>json_encode($otherdet)],"id=".$appldet['id']);
            }
        }

    return ["RegNo_Appl"=>$Param['RegNo_Appl']];
    


}

//R045
function LoadEntrancePayment($Param){
  global $dbo;
  if(!isset($Param['RegNo_Appl']) || trim($Param['RegNo_Appl']) == ""){
   // return ["PageNum"=>1,"__Alert__"=>"Sorry, we could not Identify you. Enter your Email Address and Try Again"];
    return RedirectTo(1,"Sorry, we could not Identify you. Enter your Email Address and Try Again");
}
  //get the payid for entrance payment
  //check if entrance id isset
 /*  $EntrContrID = (isset($Param["EntranceID"]) && (int)$Param["EntranceID"] > 0)?$Param["EntranceID"]:1;
  $entrancedet = $dbo->SelectFirstRow("putme","","ID=".$EntrContrID);
  if(!is_array($entrancedet))Error(52); */
  $entrancedet = Entrance($Param);
  if($entrancedet['PayReg'] == "REG"){ //if payment disabled
    if(!isset($Param['NextPageNum']))$Param['NextPageNum'] = 5;//if the next page not sent set to 5
    //update the applicant RegLevel - not needed incase payment enable during the registration process
   // $upd = $dbo->Update("pstudentinfo_tb",["RegLevel"=>$Param['NextPageNum']],"id=".$appldet['id']);
    return RedirectTo($Param['NextPageNum']);
  }
  $PayID = $entrancedet['PayID'];
  //get the applicant details
  $appldet = $dbo->SelectFirstRow("pstudentinfo_tb","","RegNo='".$dbo->SqlSafe($Param['RegNo_Appl'])."' OR JambNo='".$dbo->SqlSafe($Param['RegNo_Appl'])."'",MYSQLI_ASSOC);
  if(trim($appldet['OtherDet']) != "" && !is_null($appldet['OtherDet'])){
      $otherdetarr = json_decode($appldet['OtherDet'],true);
      if(is_array($otherdetarr)){
          unset($appldet['OtherDet']);
          $appldet = array_merge($appldet,$otherdetarr);
      }
  }
  //get payment ref
  $payorder = $dbo->SelectFirstRow("order_tb","","RegNo='".$dbo->SqlSafe($Param['RegNo_Appl'])."' AND ItemID = $PayID");
  if(is_array($payorder)){
    //check payment
  $paydet = HasPaidRef($payorder['TransNum']);
    //return ["Status"=>"Paid"];
    if($paydet[0] == 1){ //payment not made
        if(!isset($Param['NextPageNum']))$Param['NextPageNum'] = 5;//if the next page not sent set to 5
        //update the applicant RegLevel
        $upd = $dbo->Update("pstudentinfo_tb",["RegLevel"=>$Param['NextPageNum']],"id=".$appldet['id']);
        return RedirectTo($Param['NextPageNum'],"Required Payment Verified Successfully");
    }
  }

  //get the payment item details
  //$payitem = $dbo->SelectFirstRow("item_tb","","ID=".$PayID);
  //if(!is_array($payitem))Error(14); //invalid payment type
$HighSem = HighestSemester();
  //get the payment amount
  $Pamt = GetPaymentAmt(["LoginName"=>$Param['RegNo_Appl'],"SemesterID"=>($HighSem['Num']+1),"LevelID"=>1,"SemesterPartID"=>3,"PayID"=>$PayID,"StudentDetails"=>$appldet]);
  if(!is_array($Pamt))Error(12);

  //marge all details
  return array_merge($Pamt['StudentDetails'],$Pamt['PayDetails'],["Amount"=>$Pamt['Amount'],"FAmount"=>$Pamt['FAmount'],"RegNo_Appl"=>$Param['RegNo_Appl']]);
  //Error("CE",json_encode($Pamt));
  
}

//R046
//Check if Entrance module is enabled
function Entrance($Param){
    
    global $dbo;
    
    
    //check if entrance id isset
  $EntrContrID = (isset($Param["EntranceID"]) && (int)$Param["EntranceID"] > 0)?$Param["EntranceID"]:1;
  $entrancedet = $dbo->SelectFirstRow("putme","","ID=".$EntrContrID);
  if(!is_array($entrancedet))Error(52);
  if($entrancedet['Status'] == "CLOSED")Error(53,'<br/>'.$entrancedet['Title']);
  //Error("CE",json_encode(array_merge($entrancedet,$Param)));
  return array_merge($entrancedet,$Param);
}


//Internal Modul
//Redirect Apply Page
function RedirectTo($pageNum = 1,$Alert = ""){
    $rtn = ["PageNum"=>$pageNum];
    if(trim($Alert) != ""){
        $rtn["__Alert__"] = $Alert; 
    }
    return $rtn;
}


//R054
function ChangeEntranceVerField($Param){
    //Error(2);
    return $Param;
}

//Resize Image Using the Image LB
function ResizeImage($imagepth,$width,$height){
    global $dbo;
     //include the image resize lib
     if(!file_exists("../../../../".$dbo->Config['SubDir'].$dbo->Config['Require']."Image/image.php"))Error("CE","Image Proccessor Not Found");
     include "../../../../".$dbo->Config['SubDir'].$dbo->Config['Require']."Image/image.php";
     //get the image size
     list($iwidth, $iheight, $type, $attr) = getimagesize($imagepth);
     if($iwidth <= $width)return;
     $magicianObj = new imageLib($imagepth);
     $magicianObj -> resizeImage($width, $height, 'landscape', true);
     $magicianObj -> saveImage($imagepth, 100);
}

//Auto calculate dimention
function AutoFitInto($padW,$padH,$width,$height,$margin = 0){
    $orientation = "";
 $Ratio = $width / $height;
 //determin if its landscape or portraite
if($height > $width){
   $orientation = "p";
   //check if height is greater than pad hight
   if($height >= $padH){
      $height = $padH - $margin;
      //calculate new width
     $width = floor($Ratio * $height);
     
   }
   if($width >= $padW){
         $width = $padW - $margin;
         //calculate new width
         $height = floor($width / $Ratio);
       }
}else if($width > $height){
   $orientation = "l";
   //check if width is greater than pad width
   if($width >= $padW){
       $width = $padW - $margin;
       //claculate $height
       $height = floor($width / $Ratio);

   }

   if($height >= $padH){
         $height = $padH - $margin;
         //calculate new width
         $width = floor($Ratio * $height);
       }
}
//if square
if($orientation == ""){
   //$style = GetValue("style",$atrrValStr);
  if($height >= $padH){
         $height = $padH - $margin;
         //calculate new width
         $width = $height;
        
       }

        if($width >= $padW){
          $width = $padW - $margin;
          $height = $width;
         }
}
return array($width,$height,$orientation);
}

//R047
function AddReferee($Param){
    Underscored($Param);
    MapData($Param);
    global $dbo;
    
    if(!isset($Param['RegNo']) || trim($Param['RegNo']) == "")Error(11);
    $RegNo = $Param['RegNo'];
    //check the referee name
    if(!isset($Param['RefereeName']) || (!is_array($Param['RefereeName']) && trim($Param['RefereeName']) == ""))Error(54);

    //get school detatils
    $sch = GetSchool();

    //turn all expected referee details to array if not array
    foreach(['RefereeName','RefereeEmail','RefereePhone'] as $refdet){
        $Param[$refdet] = !isset($Param[$refdet])?[""]:is_array($Param[$refdet])?$Param[$refdet]:[$Param[$refdet]];
        
    }


    foreach($Param['RefereeName'] as $refkey => $refVale){
      //check if already exist 
      $RefName = $refVale;
      $RefEmail = isset($Param['RefereeEmail'][$refkey])?$Param['RefereeEmail'][$refkey]:$Param['RefereeEmail'][0];
      $RefPhone = isset($Param['RefereePhone'][$refkey])?$Param['RefereePhone'][$refkey]:$Param['RefereePhone'][0];
      //$RefPhone 
        $refexit = $dbo->SelectFirstRow("referee_tb","","Email='".$dbo->SqlSafe($RefEmail)."' AND ApplID='".$dbo->SqlSafe($RegNo)."'");
        if(is_array($refexit)) continue;

        $VeriNum = mt_rand(100000,999999);
        /* $lookup = "../../Pages/";
        if(file_exists("../../../../".$dbo->Config["SubDir"]."Pages/".$Param['Dir']."/RefMail.html")){
            $lookup = "../../../../".$dbo->Config["SubDir"]."Pages/";
        } */
  $msg = "Referee Code: <b>$VeriNum</b>";
  $Param['SchoolName'] = $sch['Name'];
  $Param['VerPin'] = $VeriNum;
   $Param['RefName'] = $RefName;
  MailMessage($msg,$Param,"RefMail.html");
        /* if(file_exists($lookup.$Param['Dir']."/RefMail.html")){
           $msg = file_get_contents($lookup.$Param['Dir']."/RefMail.html");
           if($msg != ""){
               $Param['SchoolName'] = $sch['Name'];
               $Param['VerPin'] = $VeriNum;
               $Param['RefName'] = $RefName;
               foreach($Param as $pkey=>$pval){
                   $msg = str_replace("{{".$pkey."}}",$pval,$msg);
               }
              // $msg = str_replace(["{{Logo}}","{{SchoolName}}","{{ApplEmail}}","{{VerPin}}","{{Abbr}}","{{SubDir}}","{{Core}}","{{Dir}}"],[$dbo->Config["SubDir2"]."Files/".$sch['logo'],$sch['Name'],$Param['RegNo_Appl'],$VeriNum,$sch['Abbr'],$dbo->Config['SubDir2'],$dbo->Config['Core2'],$Param['Dir']],$msg);
           }
        } */
      //return ["Mail"=>$msg];
         //send the verification number to the applicant mail
         $sendmail = $dbo->SendMail($sch['OpEmail'],$RefEmail,$Param['Subject'],$msg,$sch['OpEmail'],$sch['OpEmailPassw'],$sch['OpEmailLive']=="FALSE"?false:true);
         //return ["Mail"=>$msg];
         if($sendmail !== true){
             Error(50," : ".$sendmail);
         }
        //insert
        $inst = $dbo->InsertID("referee_tb",["Name"=>$RefName,"Email"=>$RefEmail,"Phone"=>$RefPhone,"AccessCode"=>$VeriNum,"ApplID"=>$RegNo]);
        if(!is_numeric($inst)){
          //Error("CE",$inst);
        }
    }

   

    //check if RegLevel Set, Update in pstudentinfo
    if(isset($Param['RegLevel'])){
        $upd = $dbo->Update("pstudentinfo_tb",["RegLevel"=>$Param['RegLevel']],"RegNo='".$dbo->SqlSafe($RegNo)."' OR JambNo = '".$dbo->SqlSafe($RegNo)."'");
    }

     return ["RegNo_Appl"=>$RegNo];
}

//OlevelExamTypes R048
function OlevelExamType($Param){
    global $dbo;
    $olvlextype = $dbo->Select("olevelexamtype_tb");
    if(!is_array($olvlextype))Error(4);
    return $dbo->FetchAll($olvlextype[0],MYSQLI_ASSOC);
}

//R049
function SaveOlevelDetails($Param){
    Underscored($Param);
    global $dbo;
    /* GATEWAY STANDARD ACADEMY, UKANAFUN`~2016`~4042817020`~2`~1 */
    /* ENGLISH LANGUAGE=B3;MATHEMATICS=B2;BIOLOGY=B2;CHEMISTRY=B3;PHYSICS=C5;AGRICULTURAL SCIENCE=A1;CIVIC EDUCATION=B3;MARKETTING=B2;GEOGRAPHY=B3 */
    /* 1=4||6=3||7=3||8=4||9=6||13=1||37=4||44=3||4=4 */
//Error(11,$Param['RegNo']);
    $appldet = $dbo->SelectFirstRow("pstudentinfo_tb","","RegNo='".$dbo->SqlSafe($Param['RegNo'])."' OR JambNo='".$dbo->SqlSafe($Param['RegNo'])."'",MYSQLI_ASSOC);
    if(!is_array($appldet)){
        // return ["PageNum"=>1,"__Alert__"=>"Sorry, we could not Identify you. Enter your Email Address and Try Again"];
         return RedirectTo(1,"Sorry, we could not Identify you. Enter your Email Address and Try Again");
     }
    //check if not Awaiting Result
    if(!isset($Param['ExamType']) || (int)$Param['ExamType'] < 1)Error("CE","Hoop!!, Invalid First Sitting Exam Type Specified");
    //if((int)$Param['ExamType'] > 1){ //if not awaiting result
        $FsitExmDet = [];
    $SsitExmDet = [];
    $ssitseen = false;
    $ssitallseen = true;
    $RsDetFiled = ["SchName","ExamYear","ExamNum","ExamType","ExamBatch"];
    foreach($RsDetFiled as $rstDetKey){
        if(($Param["ExamType"] > 1) && (!isset($Param[$rstDetKey]) || trim($Param[$rstDetKey]) == "" || (($rstDetKey == "ExamType" || $rstDetKey == "ExamBatch") && (int)$Param[$rstDetKey] < 1))){
            Error("CE","Hoop!!, Invalid First Sitting Result Details Supplied");
        }
        //get only the year
        if($rstDetKey == "ExamYear"){
            $arr = explode("/",$Param[$rstDetKey]);
            $Param[$rstDetKey] = $arr[2];
        }
        //if it is not Awaiting result add it
       /*  if((int)$Param["ExamType"] > 1){
            $FsitExmDet[] = $Param[$rstDetKey];
        }else{ //if awaiting result
            if($rstDetKey == "ExamType"){
                $FsitExmDet[] = $Param[$rstDetKey]; 
            }else{
                $FsitExmDet[] = "";
            }
        } */
        $FsitExmDet[] = $Param[$rstDetKey];
        
        //if it is set set seen to true
        if(isset($Param[$rstDetKey."2"]) && trim($Param[$rstDetKey."2"]) != ""){
            if($rstDetKey."2" == "ExamType2" || $rstDetKey."2" == "ExamBatch2"){ //if combobox
               if((int)$Param[$rstDetKey."2"] > 0){
                $ssitseen = true;
               }else{
                $ssitallseen = false;  
               }
            }else{
                $ssitseen = true;
            }
        }else{
            $ssitallseen = false;  
        }
        if($rstDetKey."2" == "ExamYear2" && trim($Param[$rstDetKey."2"]) != ""){
            $arr2 = explode("/",$Param[$rstDetKey."2"]);
            $Param[$rstDetKey."2"] = $arr2[2];
        }
        $SsitExmDet[] = $Param[$rstDetKey."2"];

    }
    
  

    //if not awaiting result OlvRstLB is not required
    if((int)$Param["ExamType"] > 1){
        //check if valid first sit result
       if(!isset($Param['OlvRstLB']) || count($Param['OlvRstLB']) < 1)Error(0);
    }
    
    
    
    //get all olvlsubj
    $AllSubj = $dbo->Select("olvlsubj_tb");
    $AllOlvSubj = $dbo->FetchAllByID($AllSubj[0]);
    if(!is_array($AllOlvSubj))Error(4," : Reading O/A Level Subjects");
    //get all olvlsubj
    $AllGrd = $dbo->Select("olvlgrade_tb");
    $AllOlvGrade = $dbo->FetchAllByID($AllGrd[0]);
    if(!is_array($AllOlvSubj))Error(4," : Reading O/A Level Grades");

    
    if((int)$Param["ExamType"] > 1){ //if not awaiting result
    $FSitRst = FormOlvlRst($Param['OlvRstLB'],$AllOlvSubj,$AllOlvGrade);
    //check if satisfy count condition
    $MinimumRst = 7; $MaxmumRst = 9; //should come from database
    $totrst = count($FSitRst[0]);
    if($totrst < $MinimumRst || $totrst > $MaxmumRst )Error(55," :First Sitting (Minimum: $MinimumRst , Maximum: $MaxmumRst)");
    }else{
        $FSitRst = [["AR"],["AR"]];
    }

    

    $DBRstDet = implode("`~",$FsitExmDet);
    $DBRstStr = implode(";",$FSitRst[0]);
    $DBRstID = implode("||",$FSitRst[1]);

    //Check second sitting
    //if atleast one of the result details is supplied
    if($ssitseen){
        //if not all suplied
        if(!$ssitallseen && (int)$Param["ExamType2"] > 1)Error("CE","Hoop!!, Invalid Second Sitting Result Details Supplied");
        if((int)$Param["ExamType2"] > 1){ //if not awaiting result
        $SSitRst = FormOlvlRst($Param['OlvRstLB2'],$AllOlvSubj,$AllOlvGrade);
        $totrst = count($SSitRst[0]);
        if($totrst < $MinimumRst || $totrst > $MaxmumRst )Error(55," :Second Sitting (Minimum: $MinimumRst , Maximum: $MaxmumRst)");
        }else{
            $SSitRst = [["AR"],["AR"]];
        }
        $DBRstDet .= "###".implode("`~",$SsitExmDet);
        $DBRstStr .= "###".implode(";",$SSitRst[0]);
        $DBRstID .= "###".implode("||",$SSitRst[1]);
    }
   /*  }else{
        //Awaiting result
    } */
    

    $UpdateArr = ["OlevelRstDetails"=>$DBRstDet,"OlevelRst"=>$DBRstStr,"OlevelRst2"=>$DBRstID];
    if(isset($Param['RegLevel'])){
        $UpdateArr['RegLevel'] = $Param['RegLevel'];
    }

    $upd = $dbo->Update("pstudentinfo_tb",$UpdateArr,"id=".$appldet['id']);
    if(!is_array($upd))Error(56);
    return ["RegNo_Appl"=>$Param['RegNo']];

}

//internal form olvresult $Param['OlvRstLB']
function FormOlvlRst($OlvRstLB,$AllOlvSubj,$AllOlvGrade){
    //form rst arrays
    $RstStr = [];
    $RstIDs = [];
    
    foreach($OlvRstLB as $Rst){
        if((int)$Rst['state'] != 1)continue;
        $SubID = explode("_",$Rst['id']);
        $SubID = isset($SubID[1])?$SubID[1]:$SubID[0];
        //if subject not exist continue
        if(!isset($AllOlvSubj[$SubID]))continue;

        //grade id
        $GradeID = $Rst['value'];
        //if subject grade
        if(!isset($AllOlvGrade[$GradeID]))continue;

        $RstStr[] = $AllOlvSubj[$SubID]['SubName']."=".$AllOlvGrade[$GradeID]['Grade'];
        $RstIDs[] = $SubID."=".$GradeID;

    }
    return [$RstStr,$RstIDs];
}

//R050
function GetEntranceUploads($Param){
    $entdet = Entrance($Param);
    
    if(is_null($entdet['Uploads']) || trim($entdet['Uploads']) == "")return [];
    //Error("CE","hhh");
    $upl = json_decode($entdet['Uploads'],true);
    $uplarr = [];
    foreach($upl as $Dir=>$indupl){
      if($indupl[0] == false)continue;
      $req = isset($indupl[2]) && $indupl[2] == true?"true":"false";
      $uplarr[] = ["Dir"=>$Dir,"Title"=>$indupl[1],"Required"=>$req];
    }
    return $uplarr;

}

//R051
function PerformEntranceUpload($Param){
    Underscored($Param);
    if(!isset($Param['RegNo']))Error(23);
    global $dbo;
    //Error(23,$Param['RegNo']);
    //confirm applicant
    $appldet = $dbo->SelectFirstRow("pstudentinfo_tb","","RegNo='".$dbo->SqlSafe($Param['RegNo'])."' OR JambNo='".$dbo->SqlSafe($Param['RegNo'])."'",MYSQLI_ASSOC);
    if(!is_array($appldet)){
        // return ["PageNum"=>1,"__Alert__"=>"Sorry, we could not Identify you. Enter your Email Address and Try Again"];
         return RedirectTo(1,"Applicant Identification Failed. Enter your Email Address and Try Again");
     }

     $otherdet = !is_null($appldet['OtherDet']) && trim($appldet['OtherDet']) != ""?json_decode($appldet['OtherDet'],true):[];
     if(isset($otherdet['EntranceID']))$Param['EntranceID'] = $otherdet['EntranceID'];
    //get the entrance settings
    $entdet = Entrance($Param);
    
     if(is_null($entdet['Uploads']) || trim($entdet['Uploads']) == "")return ["RegNo_Appl"=>$Param['RegNo']]; //file upload not required
    //Error("CE","hhh");
    $upl = json_decode($entdet['Uploads'],true);
    $commit = true; //determine if all file upload is successfull
    $uploaded = []; //hold all successful uploaded file path
    $ApplDir = [];
    foreach($upl as $Dir=>$indupl){
        if($indupl[0] == false)continue; //if disabled
        //form the filename
        $filename = str_replace(array("/",'\\'),"_",$Param['RegNo']); //which is the regno
        //Error("CE",$filename);
        //check if dir exist
          $rst = Uploader("../../../../".$dbo->Config['SubDir']."Files/UserImages/".$Dir."/",$Dir."_Appl",$filename);
          
          if(count($rst["Failed"]) > 0){
              //unset allready uploaded files
              if(count($uploaded) > 0){
                  foreach($uploaded as $ufile){
                      unset($ufile);
                  }
              }
              Error(17," : ".$rst["Failed"][$Dir."_Appl"]);
          }
          $sucessfiles = explode(";",$rst["Success"][$Dir."_Appl"]);
          $uploaded[] = array_merge($uploaded,$sucessfiles);
          //get the filename
          $ApplDir[$Dir] = [];
          foreach($sucessfiles as $suc){
            $filearr = explode("/",$suc);
            $ApplDir[$Dir][] = array_pop($filearr);
          }
          
        //$uplarr[] = ["Dir"=>$Dir,"Title"=>$indupl[1]];
      }
      
      $Otherdet = trim($appldet['OtherDet']) != ""?json_decode($appldet['OtherDet'],true):[];
      $Otherdet["Uploads"]=$ApplDir;
      //Error(27,json_encode($ApplDir));
      $UpdateArr = ["OtherDet"=>json_encode($Otherdet),"RegLevel"=>$Param['RegLevel']];
      //update pstudentinfo 
      $upd = $dbo->Update("pstudentinfo_tb",$UpdateArr,"id=".$appldet['id']);
    //if(!is_array($upd))Error(56);
      return ["RegNo_Appl"=>$Param['RegNo']];
}


//R053
//Check if Entrance module is enabled
function Acceptance($Param){
    
    global $dbo;
    
    
    //check if entrance id isset
  $EntrContrID = (isset($Param["FormID"]) && (int)$Param["FormID"] > 0)?$Param["FormID"]:1;
  $entrancedet = $dbo->SelectFirstRow("form_tb","","ID=".$EntrContrID);
  if(!is_array($entrancedet))Error(57);
  if($entrancedet['Status'] == "CLOSED")Error(53,'<br/>'.$entrancedet['Title']);
  return $entrancedet;
}


//R052
function LoadAcceptancePayment($Param){
    global $dbo;

    //Error(0);
    if(!isset($Param['RegNo_Cand']) || trim($Param['RegNo_Cand']) == ""){
     // return ["PageNum"=>1,"__Alert__"=>"Sorry, we could not Identify you. Enter your Email Address and Try Again"];
     
      return RedirectTo(1,"Sorry, we could not Identify you. Enter your Email Address and Try Again");
  }
    //get the payid for entrance payment
    //check if entrance id isset
   /*  $EntrContrID = (isset($Param["EntranceID"]) && (int)$Param["EntranceID"] > 0)?$Param["EntranceID"]:1;
    $entrancedet = $dbo->SelectFirstRow("putme","","ID=".$EntrContrID);
    if(!is_array($entrancedet))Error(52); */
    $entrancedet = Acceptance($Param);
    if($entrancedet['PayReg'] == "REG"){ //if payment disabled
      if(!isset($Param['NextPageNum']))$Param['NextPageNum'] = 4;//if the next page not sent set to 5
      //update the applicant RegLevel - not needed incase payment enable during the registration process
     // $upd = $dbo->Update("pstudentinfo_tb",["RegLevel"=>$Param['NextPageNum']],"id=".$appldet['id']);
      return RedirectTo($Param['NextPageNum']);
    }
    $PayID = $entrancedet['PayID'];
    //get the applicant details
    $appldet = $dbo->SelectFirstRow("pstudentinfo_tb","","RegNo='".$dbo->SqlSafe($Param['RegNo_Cand'])."' OR JambNo='".$dbo->SqlSafe($Param['RegNo_Cand'])."'",MYSQLI_ASSOC);
    if(trim($appldet['OtherDet']) != "" && !is_null($appldet['OtherDet'])){
        $otherdetarr = json_decode($appldet['OtherDet'],true);
        if(is_array($otherdetarr)){
            unset($appldet['OtherDet']);
            $appldet = array_merge($appldet,$otherdetarr);
        }
    }
    //get payment ref
    $payorder = $dbo->SelectFirstRow("order_tb","","RegNo='".$dbo->SqlSafe($Param['RegNo_Cand'])."' AND ItemID = $PayID");
    if(is_array($payorder)){
      //check payment
    $paydet = HasPaidRef($payorder['TransNum']);
      //return ["Status"=>"Paid"];
      if($paydet[0] == 1){ //payment made
          //if(!isset($Param['NextPageNum']))$Param['NextPageNum'] = 4;//if the next page not sent set to 5
          //update the applicant RegLevel
          //$upd = $dbo->Update("pstudentinfo_tb",["RegLevel"=>$Param['NextPageNum']],"id=".$appldet['id']);
          return RedirectTo(4,"Required Payment Verified Successfully");
      }
    }
  
    //get the payment item details
    //$payitem = $dbo->SelectFirstRow("item_tb","","ID=".$PayID);
    //if(!is_array($payitem))Error(14); //invalid payment type
  $HighSem = HighestSemester();
    //get the payment amount
    $Pamt = GetPaymentAmt(["LoginName"=>$Param['RegNo_Cand'],"SemesterID"=>($HighSem['Num']+1),"LevelID"=>1,"SemesterPartID"=>3,"PayID"=>$PayID,"StudentDetails"=>$appldet]);
    if(!is_array($Pamt))Error(12);
  
    //marge all details
    return array_merge($Pamt['StudentDetails'],$Pamt['PayDetails'],["Amount"=>$Pamt['Amount'],"FAmount"=>$Pamt['FAmount'],"RegNo_Cand"=>$Param['RegNo_Cand']]);
    //Error("CE",json_encode($Pamt));
    
  }

  //Internal
  //Prepare Mail Message
  function MailMessage(&$msg="",$Data=[],$markup="",$dir=""){
      global $dbo;global $Param;
      $dir = $dir == ""?$Param['Dir']:$dir;
      if(trim($markup) != ""){
        $lookup = "../../Pages/".$dir;
        if(file_exists("../../../../".$dbo->Config["SubDir"]."Pages/".$dir."/".$markup))$lookup = "../../../../".$dbo->Config["SubDir"]."Pages/".$dir;
        if(file_exists($lookup."/".$markup)){
           $msg = file_get_contents($lookup.$dir."/".$markup);
        }
      }
    
    if($msg != ""){
        if(count($Data) > 0){
            foreach($Data as $key=>$val){
                $msg = str_replace("{{".$key."}}",$val,$msg);
            }
        }
        /* $msg = str_replace(["{{Logo}}","{{SchoolName}}","{{ApplEmail}}","{{VerPin}}","{{Abbr}}","{{SubDir}}","{{Core}}","{{Dir}}"],[$dbo->Config["SubDir2"]."Files/".$sch['logo'],$sch['Name'],$Param['RegNo_Appl'],$VeriNum,$sch['Abbr'],$dbo->Config['SubDir2'],$dbo->Config['Core2'],$Param['Dir']],$msg); */
    }
    return $msg;
  }

  //PaymentBreakDown (#R055)
  function PaymentAnalysis($param){
      global $_;
      //Error(59,":".$param['PayRef']);
      //"SemesterID":1,"LevelID":1,"SemesterPartID":3,"PayID":7,"RegNo":"AD917401" "LoginName":"AD917401"
     if(!isset($param['PayRef']) || trim($param['PayRef']) == "")Error(57);
     //get the payment details
     $paydet = $_->SelectFirstRow("order_tb","TransNum,ID,Paid,BrkDwn,ItemName,Amt","TransNum='".$_->SqlSafe($param['PayRef'])."'",MYSQLI_ASSOC);
     if(!is_array($paydet))Error(58);
     //check if Paid
     if((int)$paydet['Paid'] == 1)Error(59,":".$param['PayRef']);
     //get the preakdown
     $BreakDown = $paydet['BrkDwn'];
     $Preakdarr = [];
     if(trim($BreakDown) == ""){
         $Amt = (float)$paydet['Amt'];
        $Preakdarr[] = ["AItemName"=>$paydet['ItemName'],"AAmt"=>$Amt,"AFAmt"=>number_format($Amt,2),"AItemID"=>0,"ADisabled"=>"disabled"];
     }else{
        $BreakDownarr = explode("***",$BreakDown);
       foreach ($BreakDownarr as $indbrdwn) {
           //Tuition Fee~25000~1
           $indbrdwnarr = explode("~",$indbrdwn);
           if(count($indbrdwnarr) < 3)continue;
           //check if item is optional
           //$optional = (isset($indbrdwnarr[3]) && trim($indbrdwnarr[3]) != "1")?"disabled":"";
           $unselect = (isset($indbrdwnarr[4]) && trim($indbrdwnarr[4]) != "1")?"checked":"";
           $optional = "";
           
           //if not optional
           if(isset($indbrdwnarr[3]) && trim($indbrdwnarr[3]) != "1"){
            $optional = "disabled";
           }else{
            $unselect = ""; //uncheck it
           }

           $Preakdarr[] = ["AItemName"=>strtoupper($indbrdwnarr[0]),"AAmt"=>(float)$indbrdwnarr[1],"AFAmt"=>number_format((float)$indbrdwnarr[1],2),"AItemID"=>$indbrdwnarr[2],"ADisabled"=>$optional,"AChecked"=>$unselect];
       }
     }
     if(count($Preakdarr) < 1){
        $Amt = (float)$paydet['Amt'];
        $Preakdarr[] = ["AItemName"=>$paydet['ItemName'],"AAmt"=>$Amt,"AFAmt"=>number_format($Amt,2),"AItemID"=>0,"ADisabled"=>"disabled"];
     }
     //Error("CE",json_encode(array_merge($paydet,["Analysis"=>$Preakdarr,"FAmtMain"=>number_format((float)$paydet['Amt'],2)])));
      return array_merge($paydet,["Analysis"=>$Preakdarr,"FAmtMain"=>number_format((float)$paydet['Amt'],2)]);

  }

  //UpdateOrderDet R056
  function UpdateOrderDet($param){
    
      global $_;
      if(!isset($param['PayRef']) || trim($param['PayRef']) == "")Error(57);
      if(!isset($param['PayItems']) || count($param['PayItems']) < 1)Error(60);
      //get the order details
      $paydet = $_->SelectFirstRow("order_tb","TransNum,ID,Paid,BrkDwn,ItemName,Amt,ItemID as PayID","TransNum='".$_->SqlSafe($param['PayRef'])."'",MYSQLI_ASSOC);
      if(!is_array($paydet))Error(58);

       //check if Paid
     if((int)$paydet['Paid'] == 1)Error(59);

      //prepare current breakdown
      $BreakDown = $paydet['BrkDwn'];
      $Preakdarr = [];
      $totAmt = 0;
      if(trim($BreakDown) == ""){
          $Amt = (float)$paydet['Amt'];
         $Preakdarr[0] = [$paydet['ItemName'],$Amt,0,0,0];
         $totAmt = $Amt;
      }else{
         $BreakDownarr = explode("***",$BreakDown);
        foreach ($BreakDownarr as $indbrdwn) {
            //Tuition Fee~25000~1
            $indbrdwnarr = explode("~",$indbrdwn);
            if(count($indbrdwnarr) < 3)continue;
            //check if item is optional
            $Preakdarr[$indbrdwnarr[2]] = $indbrdwnarr;
            $totAmt += (float)$indbrdwnarr[1];
        }
      }
      if(count($Preakdarr) < 1){
         $Amt = (float)$paydet['Amt'];
         $Preakdarr[0] = [$paydet['ItemName'],$Amt,0,0,0];
         $totAmt = $Amt;
      }


      //get new total and reform the payment items
      /* "PayItems":[{"type":"checkbox","id":"pitemid-1","state":1,"marker":"\u20a6 25,000.00","value":"1"},{"type":"checkbox","id":"pitemid-13","state":1,"marker":"\u20a6 2,500.00","value":"13"},{"type":"checkbox","id":"pitemid-10","state":1,"marker":"\u20a6 3,000.00","value":"10"},{"type":"checkbox","id":"pitemid-15","state":1,"marker":"\u20a6 14,500.00","value":"15"},{"type":"checkbox","id":"pitemid-8","state":0,"marker":"\u20a6 23,000.00","value":"8"}] */
      foreach($param['PayItems'] as $newbrkdwn){
         $iid = (int)$newbrkdwn['value'];
         if(!isset($Preakdarr[$iid]))continue;
         $selected = (int)$newbrkdwn['state'];
         if($selected == 0){
            $Preakdarr[$iid][4] = 1;
         }else{
            $Preakdarr[$iid][4] = 0;
         }
      }

      $NewBrkDwn = "";
      $NewTotal = 0;
      //form new break down and total
      foreach($Preakdarr as $indItem){
        if((int)$indItem[4] < 1){ //if is selected
            $NewTotal += (float)$indItem[1];
        }
        $NewBrkDwn .= implode("~",$indItem)."***";
      }

      $NewBrkDwn = rtrim($NewBrkDwn,"***");
        //Error("CE",$NewTotal." - ".json_encode($param['PayItems']));
      //update the new breakdown and amount
      $updorder = $_->Update("order_tb",["Amt"=>$NewTotal,"BrkDwn"=>$NewBrkDwn],"TransNum='".$_->SqlSafe($param['PayRef'])."'");
      if(!is_array($updorder))Error(61);

      return ["PayRef"=>$param['PayRef'],"Amt"=>$NewTotal,"FAmt"=>number_format($NewTotal,2),"ItemName"=>$paydet['ItemName'],"PayID"=>$paydet['PayID']];

      //Error("CE",$NewBrkDwn." => ".$NewTotal);
  }

  //Get all levels - R058
function GetAllLevels($Param){
    
    // Error(4,$Param['ProgID']);
     global $dbo;
     $studycond = (isset($Param['StudyID']) && (int)$Param['StudyID'] > 0)?"StudyID=".$dbo->SqlSafe($Param['StudyID']):"1=1";
     $facs = $dbo->Select("schoollevel_tb","Level as LevelID,Descr as LevelName",$studycond);
     //Error(4,$studyid);
     if(!is_array($facs))Error(4);
    
     return $dbo->FetchAll($facs[0],MYSQLI_ASSOC);
 }

 //Get all classes by progid - R059
function GetClassByProg($Param){
    global $dbo;
    if(!isset($Param['ProgID']) || (int)$Param['ProgID'] < 1)Error(11);
    $ProgID = $Param['ProgID'];
    $clases = $dbo->Select("studentclass_tb","","ProgID=".$dbo->SqlSafe($ProgID));
    if(!is_array($clases))Error(4);
    return $dbo->FetchAll($clases[0],MYSQLI_ASSOC);
}



?>
