<?php
require_once 'parseUtils.php';
require_once 'write_log.php';
include_once 'demosettings.php';

class CacheEng
{
    const ACTION_NAME_PREFIX = "dashboard_element";
    //getFromCache($cache_key,$username)
    //checks if the cache_key appears in the table cacheeng - if so - will return it or empty results
    public static function getFromCache($mysqli,  $username, $pieName){
        if (strcmp($pieName, 'caseStatistics') == 0) {
            $pieName = 'key_stats';
        }
        $stats = getTableElementData($mysqli, 'dashboard',$pieName, 'username', $username);
        
        $graphType =  $stats->type ?? "";
        
        $cache_key =  self::generate_cache_key($mysqli, $graphType, $pieName, $username);
        
        if(!isJson($cache_key)){
             $cache_key=json_encode($cache_key,true);
        }
        $sql_cache = "SELECT * FROM cacheeng WHERE cache_key =$cache_key";
        $result = sqlQuery($mysqli, $sql_cache);
        
        return $result->fetch_object();    
    }

    
    //updateResultsAndCache($cache_key,$results)
    //Update the cache with the new results per this cache_key
    public static function updateResultsAndCache($mysqli, $username,  $graph_type, $element_name, $results){
        $date = date('Y-m-d h:i:s');
        
        $cache_key = self::generate_cache_key($mysqli, $graph_type, $element_name, $username);
         
        if(is_array($results)){
            $results = json_encode($results, JSON_UNESCAPED_UNICODE); 
        }
        
        $results = $mysqli->real_escape_string($results);

        $sql = "INSERT INTO cacheeng (cache_key,results,in_process,date) VALUES('$cache_key','$results',0,'$date')
                ON DUPLICATE KEY UPDATE results = '$results', in_process=0, date='$date'";
        write_to_log("TRACE", "Cache: Update $cache_key"); 
        
        $stats = sqlQuery($mysqli, $sql);
        
        if(!($stats)){
            write_to_log("ERROR", "updateResultsAndCache problem with the sql");
        }
    }
    
    
    
    public static function update_process($mysqli, $username, $pieName, $new_val){
        if (strcmp($pieName, 'caseStatistics') == 0) {
            $pieName = 'key_stats';
        }
        $stats = getTableElementData($mysqli, 'dashboard', $pieName, 'username', $username);
        
        $graphType =  $stats->type ?? "";
        $cache_key = CacheEng::generate_cache_key($mysqli, $graphType, $pieName, $username);
                
        $sql = " UPDATE cacheeng SET in_process = $new_val WHERE cache_key ='$cache_key'";
        $stats = sqlQuery($mysqli, $sql);
    }
    
    
    public static function getCacheKey($mysqli, $username, $pieName){
        if (strcmp($pieName, 'caseStatistics') == 0) {
            $pieName = 'key_stats';
        }
        $stats = getTableElementData($mysqli, 'dashboard',$pieName, 'username', $username);
        
        $graphType =  $stats->type ?? "";
        return self::generate_cache_key($mysqli, $graphType, $pieName, $username);
    }

        

    /**
     * generate_cache_key - generate a key for the user to use infront the cache
     * We will generate the key from:
     * $graphType -$stats->type (where type is pie, trend etc)
     * $element_name - person, key stat etc
     * $isAdmin
     * $pastPeriod
     * $username_field
     *  $non_default - checks if graph is default (as entities etc) or costume (as name you saved etc)
     */
    public static function generate_cache_key($mysqli, $graph_type, $element_name, $username){ 
        $action_name = self::ACTION_NAME_PREFIX."-".$graph_type;
        //1 - check if the element does not appear in the merged array (of default element or graph of default user)
        // will create $non_default for the key
        global $defaultDashboradNames;
        global $dashboardTemplateUsername;
        $names_arr = fetchFromDefaultUser($mysqli, $dashboardTemplateUsername, $username);
        $default_user_names = $names_arr['names'];
        $merged_array = array_unique(array_merge(array_keys($default_user_names), array_keys($defaultDashboradNames)));
        
        $array_converted = array_map(function($val) {
            $val = str_replace(' ', '_', $val); 
            return strtolower($val);
        },
         $merged_array);
        
        //special case for now
        if(in_array($element_name, array('Geographical theatre','Abstract idea'))){
            $element_name = str_replace(' ', '_', $element_name);
            $element_name = TablesInformation::getTableName($element_name);
        }
        if($dashboardTemplateUsername !== $username && !in_array(strtolower($element_name ?? ""), $array_converted)){
            $non_default = ", non_default: $username";
        }
        else{
            $non_default = "";
        }
        
        //2 - gets past period
        $pastPeriod = getPastPeriod($mysqli, $username) ?? "(NULL)";
        
        //3 - gets isAdmin and username
        $isAdmin = $_REQUEST['isAdmin_override'] ?? $_REQUEST['isAdmin'] ?? self::get_admin_perm($username, $element_name);
        $username_field = (!$isAdmin) ? ", username: $username" : "";
      
        //4 - changes element name if its case Statistics
        if (strcmp($element_name ?? "", 'caseStatistics') == 0) {
            $element_name = 'key_stats';
        }
        
        // 5 - gets the type of pie from dasbhoard db table - for the $actionNmae
        $stats = getTableElementData($mysqli, 'dashboard',$element_name, 'username', $username);

        return "action: $action_name, element: $element_name, isAdmin: $isAdmin, pastPeriod: $pastPeriod". $username_field . $non_default;   
    }
    
    //get_admin_perm() - here we can control the admin permissions for the cache - some pies as systemstatus, no need for private user diff
    public static function get_admin_perm($username, $element_name){
        if($element_name=='system_status'){
            return "1";
        }
        return getUserPermission(CAN_SHOW_ALL_USER,$username)?? "0";
    }
        
    //checkLimit() - check if the limit of the table has been reached
    public static function checkLimit($mysqli){
        $query="SELECT MAX(ID) from cacheeng";
        $max = sqlQuery($mysqli, $query);
        if($max>LIMIT){
            //need to do somoethnig
            return false;
        }
        return true;
    }
    
    public static function json_encode_patch($input){
        $str=json_encode($input);
        $str=str_replace(',',', ',$str);
        return str_replace(':',': ',$str);
    } 
    
    public static function getActionName($func){
        if($func == 'system_status'){
            return "dashboard_element-status";
        }
        return "dashboard_element-pie";
    } 
  
    public static function get_cache_res($mysqli, $php_files, $class_lib, $func, $username){
        $cond_array = get_CondArr($mysqli, $func, $username);
        $results_exists = $cond_array['results_exists'];
        $in_process = $cond_array['in_process'];
        
        // 1 - status data exists
        if ($results_exists) {
                cacheEng::update_process($mysqli, $username, $func, ++$in_process);
            if (!$in_process) {  
                
                asyncRequst::getInstance()->runLibraryFunc($php_files, $class_lib, $func, $username);
            }
            $action_name = self::getActionName($func);
            
            $res = CacheEng::getFromCache($mysqli,  $username, $func);
            
            $content = $res->results;
            $content = json_decode($content, true);       
        } else{       
            $content = call_user_func($class_lib."::".$func, $username);
        }
        
      
        //will reset in process after 5 req for pie
        resetInProcessField($mysqli, $func, $username);
        
        return $content;
    }
    
    
    /**
     * Perform refreshPie function on all pies in dashboard
     * @param unknown $mysqli
     * @param unknown $username
     */
    public static function refreshCache($mysqli, $username){ 
        require_once 'StatisticPageEng.php';
        
        global $defaultDashboradNames;
        foreach($defaultDashboradNames as $table=>$arr){
            if(in_array($table, array('key_stats','System Status'))){
                continue;
            }
            CacheEng::refreshPie($mysqli, $username, $table);
        }
    }
    
    /**
     * refresh one panel
     * @param unknown $mysqli
     * @param unknown $username
     * @param unknown $table
     */
    public static function refreshPie($mysqli, $username, $table){
        require_once 'StatisticPageEng.php';     
        $pieData = getTableElementData($mysqli, 'dashboard', $table, 'username', $username);
        $pieData = json_decode(json_encode($pieData), true);
        $cache_key =  CacheEng::generate_cache_key($mysqli, $pieData["type"] ?? null, $table, $username);
        $content = json_encode(getPie($mysqli, true,  $pieData,  null));
        CacheEng::updateResultsAndCache($mysqli, $username,  $pieData["type"], $table, $content);
    }
    

    /**
     * update the JSONS of the cacheEng
     * @param unknown $mysqli
     * @param unknown $username
     * @param unknown $source_table
     * @param unknown $dest_table
     * @param unknown $entity
     */
    public static function updatePanels($mysqli, $username, $source_table, $entity, $dest_table = null){
        global $defaultDashboradNames;
        $isOrgText = getSystemSettingsProp($mysqli, "isOrgText");
        
        //fetch the table actual name
        $panels = getPanelsConfiguration($mysqli, $username, "dashboard", "1");
        
        foreach($panels['panelsConfiguration'] as $key=>$arr){
            
   
            if($arr["entity"] == $source_table){
                $source_table = $arr["name"];
            }
            if(!empty($dest_table) && $arr["entity"] == $dest_table){
                $dest_table = $arr["name"];
            }
        }
        $curr_item = [];
        $label_value = $isOrgText ? $entity["otherText"] : $entity["label"];
        $name_base64 = base64_encode($label_value);
        $fields = array("amount","popular","unpopular");
        
        
        $pieData_source = getTableElementData($mysqli, 'dashboard', $source_table, 'username', $username);
        $cache_key_source =  CacheEng::generate_cache_key($mysqli, $pieData_source->type ?? null, $source_table, $username);
        
        if(!empty($dest_table)){
            $pieData_dest = getTableElementData($mysqli, 'dashboard', $dest_table, 'username', $username);
            $cache_key_dest =  CacheEng::generate_cache_key($mysqli, $pieData_dest->type ?? null, $dest_table, $username);
        }
        foreach ($fields as $section){
            //A - First - remove from original table
            $sql ="UPDATE cacheeng SET results = JSON_REMOVE(results, '$.".$section.'."'.$name_base64."\"') WHERE cache_key='$cache_key_source';";
            $res = sqlQuery($mysqli, $sql);
            
            //B - add the element to the dest table
            if(!empty($dest_table)){
                $curr_ont = $entity["ont"] ?? null;
                $curr_label = $mysqli->real_escape_string($entity["label"]);
                
                $curr_size = $entity["size"];             
                $sql ="UPDATE cacheeng SET results = JSON_SET(results, '$.".$section.'."'.$name_base64."\"',
                 JSON_OBJECT('ont',\"$curr_ont\", 'label', \"$curr_label\", 'scale', $curr_size)) WHERE cache_key='$cache_key_dest';";               
                $res = sqlQuery($mysqli, $sql);
            }
        }
    }
    
    public static function rereshDashboard($mysqli, $isAdmin, $username){
            require_once 'demosettings.php';
            require_once 'v2'.DIRECTORY_SEPARATOR.'mainEng_funcs_v2.php';
            $panels = getPanelsConfiguration($mysqli, $username, "dashboard", "1");
            $date = date('Y-m-d h:i:s');
            
            foreach ($panels['panelsConfiguration'] as $dashboard_element){
                
                $document_res = [];
                
                $table = $dashboard_element["name"];
                write_to_log("TRACE", "Incremntal process on $table");
                
                $pieData = getTableElementData($mysqli, 'dashboard', $table, 'username', $username);
                $pieDetailsArray = getPieDetails($pieData);
                
                $_REQUEST["username"] = $username;
                $_REQUEST["isAdmin"] =   getUserPermission(CAN_SHOW_ALL_USER);
                ;
                include_once 'StatisticPageEng.php';
                
                $document_res = getPie($mysqli, true,  $pieDetailsArray,  null);
                $json_doc = $mysqli->real_escape_string(json_encode($document_res, true));
                
                
                $graphType =  $pieData->type ?? "";
                
                $cache_key =  CacheEng::generate_cache_key($mysqli, $pieData->type ?? null, $table, $username);
                
                $sql = "SELECT id from cacheeng WHERE cache_key = \"$cache_key\"";
                $res = sqlQuery($mysqli, $sql);
                $row = $res->fetch_object();
                
                //if empty - just insert to table
                if(empty($row->id)){
                    $sql = "INSERT INTO cacheeng (cache_key, results,date) VALUES(\"$cache_key\", \"$json_doc\",\"$date\")";
                    $res = sqlQuery($mysqli, $sql);
                }
                //update the new values to the cacheng table
                if(!empty($document_res)){
                    $sql = "UPDATE cacheeng SET results =  \"$json_doc\", date='$date' WHERE cache_key=\"$cache_key\"";
                    $res = sqlQuery($mysqli, $sql);
                }
                
            }
            
        
    }
    
    public static function refreshOverview($mysqli, $isAdmin, $username){
        //update the overview
        $cache_key =  CacheEng::generate_cache_key($mysqli, 'statistics', 'key_stats',  $username);
        $sql = "SELECT id from cacheeng WHERE cache_key = \"$cache_key\"";
        $res = sqlQuery($mysqli, $sql);
        $row = $res->fetch_object();
        
        $overview_stats = getStatistic($mysqli, $username, $isAdmin, false);
        
        $overview_stats = $mysqli->real_escape_string(json_encode($overview_stats, true));
        
        //if empty - just insert to table
        if(empty($row->id)){
            $sql = "INSERT INTO cacheeng (cache_key, results) VALUES(\"$cache_key\", \"$overview_stats\")";
        }
        else{
            $sql = "   UPDATE cacheeng SET  results = \"$overview_stats\"  WHERE cache_key = \"$cache_key\"";
        }
        
        $res = sqlQuery($mysqli, $sql);
        
        if(!$res){
            return "Error";
        }
        return "Success";
    }
}