<?php
/**
 * @package     Joomla.Administrator
 * @subpackage  com_pa_export
 */

defined('_JEXEC') or die;

use Joomla\Utilities\ArrayHelper;

/**
 * PA Export List Model
 *
 * @since  1.5
 */
class pa_exportModelConfigcomp extends JModelList
{
  protected $params;
  protected $irrelevant_fields;
  
  public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'section',
				'sub',
				'key',
			);
		}

		parent::__construct($config);
    
    $this->datatype = 'normal';
    
    $this->params = array();
    $this->irrelevant_fields = $this->getIrrelevantFields();
    
    $client_id = array('Site','Administrator');
    
    $get = 'content';
    
    $this->params['content'] = array(
      'table' => '#__content',
      'key' => 'alias',
      'resolve' => array(
        'catid' => array(
          'table' => '#__categories',
          'key' => 'id',
          'return' => 'title',
        ),
        'access' => array(
          'table' => '#__viewlevels',
          'key' => 'id',
          'return' => 'title',
        ),
      ),
      #'map' => array(
      #  'client_id' => $client_id),
      'function' => array(
        'introtext' => 'md5',
        'fulltext' => 'md5',
      ),
      'unset' => array('id','created','modified','checked_out','checked_out_time',
        'publish_up','publish_down','version','ordering','hits','created_by',
        'modified_by','xreference','note'),
    );
    
    $this->params['extensions'] = array(
      'table' => '#__extensions',
      'key' => 'name',
      'resolve' => array(
        'package_id' => array(
          'table' => '#__extensions',
          'key' => 'extension_id',
          'return' => 'name',
        ),
      ),
      'function' => array(
        'version' => 'json:manifest_cache:version',
      ),
      'map' => array(
        'client_id' => $client_id),
      'unset' => array('extension_id','manifest_cache','checked_out','checked_out_time',
        'ordering','custom_data','system_data'),
    );
    
    $this->params['menu'] = array(
      'table' => '#__menu',
      'key' => 'path',
      'filter' => array(
        'client_id' => 0,
        'published' => 1,
      ),
      'resolve' => array(
        'access' => array(
          'table' => '#__viewlevels',
          'key' => 'id',
          'return' => 'title',
        ),
        'parent_id' => array(
          'table' => '#__menu',
          'key' => 'id',
          'return' => 'title',
        ),
        'component_id' => array(
          'table' => '#__extensions',
          'key' => 'extension_id',
          'return' => 'element',
        ),
      ),
      'map' => array(
        'browserNav' => array(
          'gleiches Fenster',
          'neues Fenster - mit Navigation',
          'neues Fenster - ohne Navigation'
        ),
      ),
      'unset' => array('id','note','published','client_id','checked_out','checked_out_time',
        'lft','rgt'),
    );
    
    $this->params['menu_types'] = array(
      'table' => '#__menu_types',
      'key' => 'menutype',
      #'resolve' => array(
      #  'parent_id' => array(
      #    'table' => '#__usergroups',
      #    'key' => 'id',
      #    'return' => 'title',
      #  ),
      #),
      'map' => array(
        'client_id' => $client_id,
      ),
      'unset' => array('id','menutype'),
    );
    
    $this->params['user_groups'] = array(
      'table' => '#__usergroups',
      'key' => 'title',
      'resolve' => array(
        'parent_id' => array(
          'table' => '#__usergroups',
          'key' => 'id',
          'return' => 'title',
        ),
      ),
      'unset' => array('id','lft','rgt'),
    );
    
    $this->params['view_levels'] = array(
      'table' => '#__viewlevels',
      'key' => 'title',
      'resolve' => array(
        'rules' => array(
          'table' => '#__usergroups',
          'key' => 'id',
          'return' => 'title',
          'type' => 'json',
        ),
      ),
      'unset' => array('id'),
    );
  }
  
  protected function _getList($query, $limitstart = 0, $limit = 0)
  {
    $return = array();
    $list = $this->getConfigFromParams();
    
    if($limit > 0)
      return array_slice($list,$limitstart,$limit);
    
    return $list;
  }
  
  protected function _getListCount($query)
  {
    return count($this->getConfigFromParams());
  }
  
  public function getParams()
  {
    return $this->params;
  }
  
  public function getDatatype()
  {
    return $this->datatype;
  }
  
  private function getConfigFromParams($dont_apply_filter=false)
  {
    static $list;
    
    if(!is_array($list))
    {
      $config = array();
      $list = array();
      
      $config['global_config'] = $this->getGlobalConfig();
      
      foreach($this->getGlobalConfig() as $skey=>$value)
      {
        $list[] = (object)array(
          'section' => 'global_config',
          'sub' => '-',
          'key' => $skey,
          'value' => $value,
        );
      }
      
      foreach($this->params as $pkey=>$params)
      {
        $temp = $this->getConfigTable($params);
        
        if($temp)
        {
          foreach($temp as $sub=>$section)
          {
            foreach($section as $skey=>$value)
            {
              $list[] = (object)array(
                'section' => mb_convert_encoding($pkey, "UTF-8", "UTF-8"),
                'sub' => mb_convert_encoding($sub, "UTF-8", "UTF-8"),
                'key' => mb_convert_encoding($skey, "UTF-8", "UTF-8"),
                'value' => mb_convert_encoding($value, "UTF-8", "UTF-8"),
              );
            }
          }
        }
      }
      
      /*foreach($config as $key=>$section)
      {
        foreach($section as $skey=>$value)
        {
          $list[] = (object)array(
            'section' => $key,
            'key' => $skey,
            'value' => $value,
          );
        }
      }*/
      
      $list = $this->addCompareData($list);
    }
    
    $flist = $list;
    
    $result = $this->getState('filter.result');
    if(!$dont_apply_filter && $result)
    {
      foreach($flist as $key=>$item)
      {
        if(($result == 'a' && ($item->result == 'o' || $item->result == 'i')) || ($result <> 'a' && $item->result <> $result))
          unset($flist[$key]);
      }
    }
    
    if($this->getState('filter.section') || $this->getState('filter.sub') || $this->getState('filter.key'))
    {
      foreach($flist as $key=>&$item)
      {
        if(($dont_apply_filter <> 'section' && !empty($this->getState('filter.section')) && $this->getState('filter.section') <> $item->section) ||
           ($dont_apply_filter <> 'sub' && !empty($this->getState('filter.sub')) && $this->getState('filter.sub') <> $item->sub) ||
           ($dont_apply_filter <> 'key' && !empty($this->getState('filter.key')) && $this->getState('filter.key') <> $item->key))
        {
          unset($flist[$key]);
        }
        else
        {
          $item->id = implode('__',array($item->section,$item->sub,$item->key));
        }
      }
    }
    
    return $flist;
  }
  
  private function getGlobalConfig()
  {
    $config = new JConfig();
    
    $config = (array)$config;
    
    foreach(array('password','secret','smtppass','proxy_pass','ftp_pass') as $field)
    {
      if($config[$field])
        $config[$field] = md5($config[$field]);
    }
    
    return $config;
  }
  
  private function getConfigTable($params)
  {
    $db = JFactory::getDbo();
    $query = $db->getQuery(true);
    
    $query->select('*')
          ->from($db->quoteName($params['table']));
    
    if(is_array($params['filter']))
    {
      foreach($params['filter'] as $filter_field=>$filter_value)
      {
        $query->where($db->quoteName($filter_field) .' = '. $db->quote($filter_value));
      }
    }
    
    $db->setQuery($query);
    
    $list = array();
    $temp = $db->loadAssocList();
    
    foreach($temp as $item)
    {
      $key = strtolower($item[$params['key']]);
      
      if(is_array($params['resolve']))
      {
        foreach($params['resolve'] as $rkey=>$resolve)
        {
          if($resolve['type'] == 'json')
          {
            $values = json_decode($item[$rkey]);
            $item[$rkey] = array();
            
            if(is_array($values))
            {
              foreach($values as $value)
              {
                $item[$rkey][] = $this->getRecordField($resolve['table'],$resolve['key'],$value,$resolve['return']);
              }
            }
            
            sort($item[$rkey]);
            $item[$rkey] = implode(', ',$item[$rkey]);
          }
          else
          {
            $item[$rkey] = $this->getRecordField($resolve['table'],$resolve['key'],$item[$rkey],$resolve['return']);
          }
        }
      }
      
      if(is_array($params['function']))
      {
        foreach($params['function'] as $rkey=>$function)
        {
          if(substr($function,0,5) == 'json:')
          {
            $function = explode(':',$function);
            $json_data = @json_decode($item[$function[1]],true);
            
            if($json_data)
            {
              $item[$rkey] = $json_data[$function[2]];
            }
          }
          else
          {
            $item[$rkey] = call_user_func($function,$item[$rkey]);
          }
        }
      }
      
      if(is_array($params['map']))
      {
        foreach($params['map'] as $rkey=>$mapping)
        {
          if($mapping[$item[$rkey]])
          {
            $item[$rkey] = $mapping[$item[$rkey]];
          }
        }
      }
      
      if(is_array($params['unset']))
      {
        foreach($params['unset'] as $unset)
        {
          unset($item[$unset]);
        }
      }
      
      if(empty($params['key']))
        $list[] = $item;
      else
        $list[$key] = $item;
    }
    
    return $list;
  }
  
  private function addCompareData($list)
  {
    if(JFactory::getApplication()->input->get('view') == 'configcomp')
    {
      $compare_file = pa_exportHelper::getCompareFilePath();
      
      if(JFile::exists($compare_file))
      {
        $this->datatype = 'compare';
        
        $compare = json_decode(JFile::read($compare_file));
        
        $compare = pa_exportHelper::arrayValuesToKey($compare);
        $current = pa_exportHelper::arrayValuesToKey($list);
        
        #vd(array_diff_key($compare,$current));
        #vd(array_diff_key($current,$compare));
        
        foreach($list as $item_key=>&$item)
        {
          $key = implode('__',array(
            $item->section,
            $item->sub,
            $item->key,
          ));
          
          $item->compare = '';
          $item->result = 'o';
          
          if(!in_array($key,$this->irrelevant_fields))
          {
            if($compare[$key])
            {
              $item->compare = $compare[$key]->value;
              
              if($item->compare <> $item->value)
              {
                $item->result = 'd';
                
                if(pa_exportHelper::isJson($item->value) || pa_exportHelper::isJson($item->compare))
                {
                  if(pa_exportHelper::isJson($item->value))
                    $item->value = preg_replace("(\r\n|\r|\n)","<br>",print_r(json_decode($item->value),true));
                  
                  if(pa_exportHelper::isJson($item->compare))
                    $item->compare = preg_replace("(\r\n|\r|\n)","<br>",print_r(json_decode($item->compare),true));
                  
                  $c = get_decorated_diff($item->value,$item->compare);
                  
                  $item->value = $c['old'];
                  $item->compare = $c['new'];
                }
              }
            }
            else
            {
              $item->result = 'mc';
            }
          }
          else
          {
            $item->result = 'i';
          }
          
          #if($item->result == 'Ok')
          #  unset($list[$item_key]);
        }
        
        unset($item);
        
        foreach(array_diff_key($compare,$current) as $item)
        {
          $key = implode('__',array(
            $item->section,
            $item->sub,
            $item->key,
          ));
          
          $item->compare = $item->value;
          $item->value = '';
          $item->result = in_array($key,$this->irrelevant_fields) ? 'i' : 'ml';
          
          $list[] = $item;
        }
        
        #vd($list);
        
        #die();
      }
    }
    
    return $list;
  }
  
  private function getRecordField($table,$pk,$id,$field)
  {
    $db = JFactory::getDbo();
    $query = $db->getQuery(true);
    
    $query->select($db->quoteName($field))
          ->from($db->quoteName($table))
          ->where($db->quoteName($pk) .' = '. $db->quote($id));
    
    $db->setQuery($query);
    
    #var_dump((string)$query);
    
    $result = $db->loadRow();
    
    return $result[0];
  }
  
  protected function populateState($ordering = null, $direction = null)
  {
    /*$app = JFactory::getApplication();
    
    
    $ordering = $app->getUserStateFromRequest($this->context.'filter_order', 'filter_order', 'priority', 'cmd');
    if (!empty($ordering))
    {
      $list             = $app->getUserState($this->context . '.list');
      $list['ordering'] = $app->input->get('filter_order');
      $app->setUserState($this->context . '.list', $list);
    }
    
    
    $orderingDirection = $app->getUserStateFromRequest($this->context.'filter_order_Dir', 'filter_order_Dir', 'desc', 'cmd');
    if (!empty($orderingDirection))
    {
      $list              = $app->getUserState($this->context . '.list');
      $list['direction'] = $app->input->get('filter_order_Dir');
      $app->setUserState($this->context . '.list', $list);
    }*/
    
    
    $result = $this->getUserStateFromRequest($this->context . '.result', 'result', '', 'cmd');
		$this->setState('filter.result', $result);
    
    
    parent::populateState($ordering,$direction);
  }
  
  public function getItemsFieldGrouped($field)
  {
    $return = array();
    $list = $this->getConfigFromParams($field);
    
    foreach($list as $item)
    {
      $return[$item->{$field}] = $item->{$field};
    }
    
    return $return;
  }
  
  public function getIrrelevantFields()
  {
    static $data;
    
    if(is_array($data))
      return $data;
    
    $file = pa_exportHelper::getIrrelevantFilePath();
    
    if(JFile::exists($file))
    {
      $data = trim(file_get_contents($file));
      
      if($data)
      {
        $data = preg_split('@\r\n|\r|\n@',$data);
        
        if(count($data))
          return $data;
      }
    }
    
    return array();
  }
  
  public function setIrrelevantFields($data)
  {
    $file = pa_exportHelper::getIrrelevantFilePath();
    $data = implode("\r\n",$data);
    
    return JFile::write($file,$data);
  }
}
