<?php

/**
 * @version        1.14.0
 * @package        Joomla
 * @subpackage     Edocman
 * @author         Tuan Pham Ngoc
 * @copyright      Copyright (C) 2011 - 2025 Ossolution Team
 * @license        GNU/GPL, see LICENSE.php
 */

// No direct access.
defined('_JEXEC') or die;
use Joomla\CMS\Factory;
use Joomla\Filesystem\File;
use Joomla\Filesystem\Path;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Plugin\PluginHelper;
use Joomla\Filesystem\Folder;

class EDocmanModelCategory extends OSModelAdmin
{
	/**
	 * Method to get the form for the model.
	 *
	 * @param    array   $data     An optional array of data for the form.
	 * @param    boolean $loadData True if the form is to load its own data (default case), false if not.
	 *
	 * @return    JForm    A JForm object
	 */
	public function getForm($data = [], $loadData = true)
	{
		$form = parent::getForm($data, $loadData);
		$form->setFieldAttribute('category_layout', 'directory', JPATH_ROOT . '/components/com_edocman/view/category/tmpl');

		return $form;
	}

	/**
	 * Override loadData method to process path of category
	 */
	public function loadData()
	{
		parent::loadData();
		if ($this->data->path)
		{
			// Strip parent document path
			$pos = strrpos($this->data->path, '/');
			if ($pos !== false)
			{
				$this->data->path = substr($this->data->path, $pos + 1);
			}
		}

		if($this->data->owner_group_ids == '')
		{
			$this->data->owner_group_ids = '-1';
		}
	}

	
	/**
	 * Store Category
	 *
	 * @param OSInput $input
	 *
	 * @return bool|void
	 * @throws Exception
	 */
	public function save($input)
	{
		$config = EDocmanHelper::loadConfig();
		// Initialise variables;
        $db   = $this->getDbo();
		$query = $db->getQuery(true);
		$row  = $this->getTable();
		$data = $input->get('jform', [], 'array');
		//print_r($data);die();
		$id   = (int) $data['id'];

		// Delete old image if needed
		if ($id > 0)
		{
			if($id == $data['parent_id'])
			{
				throw new Exception (Text::_('EDOCMAN_CANNOT_SELECT_PARENT_CATEGORY'));
			}
			if ($id > 0 && $data['parent_id'] > 0) {
				if ($this->isCircularReference($id, $data['parent_id'])) {
					throw new Exception(Text::_('EDOCMAN_CATEGORY_CIRCULAR_REFERENCE_ERROR'));
				}
			}
			$row->load($id);
			if ($input->has('del_image') && $row->image)
			{
				$categoryImagePath      = JPATH_ROOT . '/media/com_edocman/category/';
				$thumbCategoryImagePath = $categoryImagePath . 'thumbs/';
				if (is_file(Path::clean($categoryImagePath . $row->image)))
				{
					File::delete($categoryImagePath . $row->image);
				}
				if (is_file(Path::clean($thumbCategoryImagePath . $row->image)))
				{
					File::delete($thumbCategoryImagePath . $row->image);
				}
				$data['image'] = '';
			}
			if($config->get('activate_herachical_folder_structure'))
			{
				$row->oldPath = $row->path;
			}
		}
		//Process image upload
		$files = $input->files->get('jform');
		$image = $files['image'];
		if (is_uploaded_file($image['tmp_name']))
		{
			if (!getimagesize($image['tmp_name']))
			{
				throw new Exception(Text::_('EDOCMAN_IMAGE_ERROR'));
			}
			$categoryImagePath      = JPATH_ROOT . '/media/com_edocman/category/';
			$thumbCategoryImagePath = $categoryImagePath . 'thumbs/';
			if($config->get('make_filename_safely'))
			{
				$fileName               = File::makeSafe($image['name']);
			}
			else
			{
				$fileName				= $image['name'];
			}
			if (File::upload($image['tmp_name'], $categoryImagePath . $fileName))
			{
				$width  = $config->get('category_thumb_width') ;
				$height = $config->get('category_thumb_height') ;
				//Perform resizing image
				EdocmanHelper::resizeImage($categoryImagePath . $fileName, $thumbCategoryImagePath . $fileName, $width, $height);
				if ($row->image)
				{
					if (is_file(Path::clean($categoryImagePath . $row->image)))
					{
						File::delete($categoryImagePath . $row->image);
					}
					if (is_file(Path::clean($thumbCategoryImagePath . $row->image)))
					{
						File::delete($thumbCategoryImagePath . $row->image);
					}
				}
				$data['image'] = $fileName;
			}
		}

		if (PluginHelper::isEnabled('edocman', 'notification'))
		{
			if (isset($data['notify_group_ids']))
			{
				$data['notify_group_ids'] = implode(',', $data['notify_group_ids']);
			}
			else
			{
				$data['notify_group_ids'] = '';
			}
		}

		//For Save As copy, if no thumbnail image uploaded, we just use thumbnail from original record
		if ($input->get('task') == 'save2copy' && empty($data['image']))
		{
			$originalCategory = clone $row;
			$originalCategory->load($input->getInt('id'));
			$data['image'] = $originalCategory->image;
		}

		if($config->get('activate_herachical_folder_structure') && $input->get('task') == 'save2copy')
		{
			$originalCategory = clone $row;
			$originalCategory->load($input->getInt('id'));
			$originalPath = $originalCategory->path;
			$originalPath = explode("/", $originalPath);
			$data['path'] = $originalPath[count($originalPath) - 1]."_copy";
		}

		//access level
		$query = $db->getQuery(true);
		$query->select('`access`,accesspicker,owner_group_ids,user_ids')->from('#__edocman_categories')->where('id='.$data['parent_id']);
		$db->setQuery($query);
		$parentCategory = $db->loadObject();
        if($data['accesspicker'] == 1)
		{
		    $data['access'] = 255;
			$data['groups'] = $input->get('groups',[],'array');
			
        }
		elseif($data['accesspicker'] == 2 && $data['parent_id'] > 0)
		{
			$data['access']			= $parentCategory->access;
			//$data['accesspicker']	= $parentCategory->accesspicker;
			$query->clear();
			$query->select('`groups`')->from('#__edocman_levels')->where('data_type = 0 and item_id = '.$data['parent_id']);
			$db->setQuery($query);
			$groups = $db->loadResult();
			$data['groups'] = explode(",",$groups);
		}

		if($config->owner_inheritance_categories && $data['parent_id'] > 0)
		{
			$data['user_ids']			= $parentCategory->user_ids;
			$data['owner_group_ids']	= $parentCategory->owner_group_ids;
		}
		else
		{
		
			if(count((array)$data['group_ids']) > 0)
			{
				$group_ids                      = $data['group_ids'];
				$group_ids                      = implode(",",$group_ids);
				$data['owner_group_ids']        = $group_ids;
			}
			else
			{
				$data['owner_group_ids']        = "";
			}
		}

		//Store the modified jform data back to input object for processing in parent class
		$input->set('jform', $data);
		parent::save($input);

		$category_id = $input->getInt('id');
		if($category_id > 0)
		{
            $query->clear();
            $query->select('count(id)')->from('#__edocman_levels')->where('data_type = 0')->where('item_id = '.$category_id);
            $db->setQuery($query);
            $count = $db->loadResult();

            $groups = (array)$data['groups'];
            $groups = implode(",",$groups);
			
			
            if($count == 0)
			{
                $db->setQuery("Insert into #__edocman_levels (id,data_type,item_id,`groups`) values (NULL,'0',$category_id,'".$groups."')");
                $db->execute();
            }
			else
			{
                $db->setQuery("Update #__edocman_levels set `groups` = '".$groups."' where data_type = 0 and item_id = $category_id");
                $db->execute();
            }
        }

		//update for child categories with accesspicker = 2 
		$db->setQuery("Select * from `#__edocman_categories` where parent_id = '$category_id' and `accesspicker` = 2");
		$child_categories = $db->loadObjectList();
		if(count($child_categories) > 0)
		{
			$access			= $data['access'];
			$accesspicker	= $data['accesspicker'];
			$query			= $db->getQuery(true);
			$query->select('`groups`')->from('#__edocman_levels')->where('data_type = 0 and item_id = '.$category_id);
			$db->setQuery($query);
			$groups			= $db->loadResult();
			$groups			= explode(",",$groups);
			
			foreach($child_categories as $child)
			{
				$db->setQuery("Update #__edocman_categories set `access` = '$access', `accesspicker` = '$accesspicker' where id = '".$child->id."'");
				$db->execute();

				$query->clear();
				$query->select('count(id)')->from('#__edocman_levels')->where('data_type = 0')->where('item_id = '.$child->id);
				$db->setQuery($query);
				$count = $db->loadResult();

				if((int)$groups[0] > 0)
				{
					$groupValue = implode(",",(array)$groups);
					if($count == 0)
					{
						$db->setQuery("Insert into #__edocman_levels (id,data_type,item_id,`groups`) values (NULL,'0',".$child->id.",'".$groupValue."')");
						$db->execute();
					}
					else
					{
						$db->setQuery("Update #__edocman_levels set `groups` = '".$groupValue."' where data_type = 0 and item_id = ".$child->id);
						$db->execute();
					}
				}
			}
			

			if ($config->owner_inheritance_categories && !empty($child_categories)) 
			{
				$ids = array_map(fn($child) => (int) $child->id, $child_categories); 
				$idsList = implode(',', $ids);

				$query->clear()
					->update($db->quoteName('#__edocman_categories'))
					->set($db->quoteName('user_ids') . ' = ' . $db->quote($data['user_ids']))
					->set($db->quoteName('owner_group_ids') . ' = ' . $db->quote($data['owner_group_ids']))
					->where($db->quoteName('id') . ' IN (' . $idsList . ')');

				$db->setQuery($query);
				$db->execute();
			}
		}

		//update access level for documents of this category
		$db->setQuery("Select a.id from #__edocman_documents as a inner join #__edocman_document_category as b on a.id = b.document_id where b.is_main_category = '1' and b.category_id = '$category_id'");
		$documents = $db->loadObjectList();
		if(count($documents))
		{
			if($config->access_level_inheritance)
			{
				
				$access			= $data['access'];
				$accesspicker	= $data['accesspicker'];
				$query			= $db->getQuery(true);
				$query->select('`groups`')->from('#__edocman_levels')->where('data_type = 0 and item_id = '.$category_id);
				$db->setQuery($query);
				$groups			= $db->loadResult();
				$groups			= explode(",",$groups);
				if((int) $groups[0] > 0)
				{
					foreach($documents as $document)
					{
						$db->setQuery("Update #__edocman_documents set `access` = '$access', `accesspicker` = '$accesspicker' where id = '".$document->id."'");
						$db->execute();

						$query->clear();
						$query->select('count(id)')->from('#__edocman_levels')->where('data_type = 1')->where('item_id = '.$document->id);
						$db->setQuery($query);
						$count = $db->loadResult();

						$groupValue = implode(",",(array)$groups);
						if($count == 0)
						{
							$db->setQuery("Insert into #__edocman_levels (id,data_type,item_id,`groups`) values (NULL,'0',".$document->id.",'".$groupValue."')");
							$db->execute();
						}
						else
						{
							$db->setQuery("Update #__edocman_levels set `groups` = '".$groupValue."' where data_type = 1 and item_id = ".$document->id);
							$db->execute();
						}
					}
				}
			}
			
			if($config->owner_inheritance)
			{
				foreach($documents as $document)
				{
					$db->setQuery("Update #__edocman_documents set user_ids = '".$data['user_ids']."', `owner_group_ids` = '".$data['owner_group_ids']."' where id = '".$document->id."'");
					$db->execute();
				}
			}
		}
	}

	/**
	 * Kiểm tra xem $parentId có nằm trong cây con của $categoryId không
	 * Trả về true nếu có vòng lặp (không hợp lệ)
	 */
	protected function isCircularReference($categoryId, $parentId)
	{
		if ($parentId == 0 || $categoryId == 0) {
			return false;
		}

		$db = $this->getDbo();
		while ($parentId > 0) {
			if ($parentId == $categoryId) {
				return true; // Phát hiện vòng lặp
			}
			$query = $db->getQuery(true)
				->select('parent_id')
				->from('#__edocman_categories')
				->where('id = ' . (int)$parentId);
			$db->setQuery($query);
			$parentId = (int) $db->loadResult();
		}
		return false;
	}

	/**
	 *
	 * Prepare the category data, before saving record to database
	 *
	 * @param JTable $row
	 * @param string $task
	 * @param array  $data
	 */
	protected function prepareTable($row, $task, $data = array())
	{
		$config			= EDocmanHelper::loadConfig();
		$db				= $this->getDbo();
		$query			= $db->getQuery(true);
		$id				= (int) $data['id'];
		$oldPath		= "";

		// Delete old image if needed
		if ($id > 0)
		{
			if(!EDocmanHelper::isDropBoxTurnedOn() && !EDocmanHelper::isGdriveTurnedOn() && !EDocmanHelper::isAmazonS3TurnedOn())
			{
				$row1		= $this->getTable();
				$row1->load($id);
				if($config->get('activate_herachical_folder_structure'))
				{
					$oldPath = $row1->path;

					if($oldPath != "")
					{	
						$oldFullpath = $config->get('documents_path') . '/' . $oldPath;
						if(!is_dir(Path::clean($oldFullpath)))
						{
							Folder::create(Path::clean($oldFullpath));
						}
					}
				}
			}
		}
		else
		{
			//new document
			if(!EDocmanHelper::isDropBoxTurnedOn() && !EDocmanHelper::isGdriveTurnedOn() && !EDocmanHelper::isAmazonS3TurnedOn())
			{
				if($config->get('activate_herachical_folder_structure'))
				{
					$oldPath = $data['path'];

					if ($row->parent_id > 0)
					{
						$query->clear();
						$query->select('`path`')
							->from('#__edocman_categories')
							->where('id = '. (int) $row->parent_id);
						$db->setQuery($query);
						$parentCategoryPath = $db->loadResult();
						if ($parentCategoryPath)
						{
							if($config->get('make_filename_safely'))
							{
								$parentCategoryPath = Folder::makeSafe($parentCategoryPath);
							}
							//$path = $parentCategoryPath . '/' . $path;
						}
					}

					if($oldPath != "")
					{
						$row->path = $parentCategoryPath .'/'. $oldPath;
						$oldFullpath = $config->get('documents_path') . '/' . $parentCategoryPath .'/'. $oldPath;
						if(!is_dir(Path::clean($oldFullpath)))
						{
							Folder::create($oldFullpath);
						}
					}
				}
			}
		}

		$query			= $db->getQuery(true);


		if ($row->path && $oldPath == "")
		{
			//$config    = EDocmanHelper::loadConfig();
			$force_lower_case = $config->get('force_lower_case',1);
			$path      = str_replace("\\", "/", $row->path);
			if($force_lower_case == 1)
			{
				$path      = strtolower($path);
			}
			if($config->get('make_filename_safely'))
			{
				$path      = Folder::makeSafe($path);
			}
			// In case parent category has it own folder, children category should be stored in a child folder of parent category
			if ($row->parent_id > 0)
			{
				$query->select('`path`')
					->from('#__edocman_categories')
					->where('id = '. (int) $row->parent_id);
				$db->setQuery($query);
				$parentCategoryPath = $db->loadResult();
				if ($parentCategoryPath)
				{
					if($config->get('make_filename_safely'))
					{
						$parentCategoryPath = Folder::makeSafe($parentCategoryPath);
					}
					$path = $parentCategoryPath . '/' . $path;
				}
			}
			$row->path = $path;
			$path      = $config->get('documents_path') . '/' . $row->path;
			if (!is_dir(Path::clean($path)) && $config->get('activate_herachical_folder_structure'))
			{
				Folder::create($path);
			}
		}
		elseif ($row->path && $oldPath != "" && $row->path != $oldPath)
		{
			$force_lower_case = $config->get('force_lower_case',1);
			$path      = str_replace("\\", "/", $row->path);
			if($force_lower_case == 1)
			{
				$path      = strtolower($path);
			}
			if($config->get('make_filename_safely'))
			{
				$path      = Folder::makeSafe($path);
			}
			// In case parent category has it own folder, children category should be stored in a child folder of parent category
			if ($row->parent_id > 0)
			{
				$query->select('`path`')
					->from('#__edocman_categories')
					->where('id = '. (int) $row->parent_id);
				$db->setQuery($query);
				$parentCategoryPath = $db->loadResult();
				if ($parentCategoryPath)
				{
					if($config->get('make_filename_safely'))
					{
						$parentCategoryPath = Folder::makeSafe($parentCategoryPath);
					}
					$path = $parentCategoryPath . '/' . $path;
					$db->setQuery("Update #__edocman_categories set `path` = '$path' where id = '$row->id'");
					$db->execute();
				}
			}
			else
			{
				$path = $row->path;
				$db->setQuery("Update #__edocman_categories set `path` = '$path' where id = '$row->id'");
				$db->execute();
			}

			$nPath	   = $row->path;
			$oOldPath  = $oldPath;
			$row->path = $path;
			$path      = $config->get('documents_path') . '/' . $row->path;
			$oldPath   = $config->get('documents_path') . '/' . $oldPath;

			if (is_dir(Path::clean($oldPath)) && $config->get('activate_herachical_folder_structure') && $oOldPath != $row->path)
			{
				EdocmanHelper::recurse_copy($oldPath, $path);
				//change file name of documents of this category
				$db->setQuery("Select a.id, a.filename from #__edocman_documents as a inner join #__edocman_document_category as b on a.id = b.document_id where b.category_id = '$row->id' and b.is_main_category = '1'");
				$documents = $db->loadObjectList();
				if(count($documents))
				{
					foreach($documents as $document)
					{
						$filename = $document->filename;
						$filename = str_replace($oOldPath."/", $row->path."/", $filename);
						$db->setQuery("Update #__edocman_documents set `filename` = ".$db->quote($filename)." where id = '$document->id'");
						$db->execute();
					}

				}
				EdocmanHelper::updateSubCategoryPaths($row->id);
			}
		}
		elseif ($row->path && $oldPath != "" && $row->path == $oldPath)
		{
			$force_lower_case = $config->get('force_lower_case',1);
			$path      = str_replace("\\", "/", $row->path);
			if($force_lower_case == 1)
			{
				$path      = strtolower($path);
			}
			if($config->get('make_filename_safely'))
			{
				$path      = Folder::makeSafe($path);
			}
			// In case parent category has it own folder, children category should be stored in a child folder of parent category
			if ($row->parent_id > 0)
			{
				$query->select('`path`')
					->from('#__edocman_categories')
					->where('id = '. (int) $row->parent_id);
				$db->setQuery($query);
				$parentCategoryPath = $db->loadResult();
				if ($parentCategoryPath)
				{
					if($config->get('make_filename_safely'))
					{
						$parentCategoryPath = Folder::makeSafe($parentCategoryPath);
					}
					$path = $parentCategoryPath . '/' . $path;
					$db->setQuery("Update #__edocman_categories set `path` = '$path' where id = '$row->id'");
					$db->execute();
				}
			}
			else
			{
				$path = $row->path;
				$db->setQuery("Update #__edocman_categories set `path` = '$path' where id = '$row->id'");
				$db->execute();
			}

			if($path != $oldPath)
			{
				
				//$nPath	   = $row->path;
				$oOldPath  = $oldPath;
				$oldPath   = $config->get('documents_path') . '/' . $row->path;
				$row->path = $path;
				$path      = $config->get('documents_path') . '/' . $path;
				if(!is_dir(Path::clean($path)))
				{
					Folder::create($path);
				}
				

				if (is_dir(Path::clean($oldPath)) && $config->get('activate_herachical_folder_structure'))
				{
					EdocmanHelper::recurse_copy($oldPath, $path);
					//change file name of documents of this category
					$db->setQuery("Select a.id, a.filename from #__edocman_documents as a inner join #__edocman_document_category as b on a.id = b.document_id where b.category_id = '$row->id' and b.is_main_category = '1'");
					$documents = $db->loadObjectList();
					if(count($documents))
					{
						foreach($documents as $document)
						{
							$filename = $document->filename;
							$filename = str_replace($oOldPath."/", $row->path."/", $filename);
							$db->setQuery("Update #__edocman_documents set `filename` = ".$db->quote($filename)." where id = '$document->id'");
							$db->execute();
						}

					}

					EdocmanHelper::updateSubCategoryPaths($row->id);
				}
			}
		}



		if ($row->parent_id > 0)
		{
			// Calculate level
			$query->clear();
			$query->select('`level`')
				->from('#__edocman_categories')
				->where('id = '. (int) $row->parent_id);
			$db->setQuery($query);
			$row->level = (int) $db->loadResult() + 1;
		}
		else
		{
			$row->level = 1;
		}

		parent::prepareTable($row, $task, $data);
		
		//in case path value of category is empty

        if($row->path == "")
        {
            $row->path = $row->alias;
            $config    = EDocmanHelper::loadConfig();
			$force_lower_case = $config->get('force_lower_case',1);
            $path      = str_replace("\\", "/", $row->path);
			if($force_lower_case == 1)
			{
				$path      = strtolower($path);
			}
			if($config->get('make_filename_safely'))
			{
				$path      = Folder::makeSafe($path);
			}
            // In case parent category has it own folder, children category should be stored in a child folder of parent category
            if ($row->parent_id > 0)
            {
                $query->clear();
                $query->select('`path`')
                    ->from('#__edocman_categories')
                    ->where('id = '. (int) $row->parent_id);
                $db->setQuery($query);
                $parentCategoryPath = $db->loadResult();
                if ($parentCategoryPath)
                {
					if($config->get('make_filename_safely'))
					{
						$parentCategoryPath = Folder::makeSafe($parentCategoryPath);
					}
                    $path = $parentCategoryPath . '/' . $path;
                }
            }
            $row->path = $path;
            $path      = $config->get('documents_path') . '/' . $row->path;
            if (!is_dir(Path::clean($path)) && $config->get('activate_herachical_folder_structure'))
            {
                Folder::create($path);
            }
        }
		
	}

	/**
	 * A protected method to get a set of ordering conditions.
	 *
	 * @param JTable A record object.
	 *
	 * @return array  An array of conditions to add to add to ordering queries.
	 */
	protected function getReorderConditions($table)
	{
		$condition   = [];
		$condition[] = ' parent_id = ' . (int) $table->parent_id;

		return $condition;
	}

	/**
	 * Method to check if the current user can delete the record
	 *
	 * @param EDocmanTableCategory $row
	 *
	 * @return boolean
	 */

	protected function canDelete($row)
	{
		if (!empty($row->id))
		{
			return Factory::getApplication()->getIdentity()->authorise('core.delete', 'com_edocman.category.' . (int) $row->id);
		}
		else
		{
			return parent::canDelete($row);
		}
	}

	/**
	 * Method to check if the current user can change status of the record
	 *
	 * @see OSModelForm::canEditState()
	 */
	protected function canEditState($row)
	{
		if (!empty($row->id))
		{
			return Factory::getApplication()->getIdentity()->authorise('core.edit.state', 'com_edocman.category.' . (int) $row->id);
		}
		else
		{
			return parent::canEditState($row);
		}
	}

	/**
	 * Override getData method to process notify group ids
	 *
	 * @return array|object
	 */
	public function getData()
	{
	    $db = $this->getDbo();
		if (empty($this->data))
		{
			$data = parent::getData();
			if ($data->id && PluginHelper::isEnabled('edocman', 'notification'))
			{
				$data->notify_group_ids = explode(',', $data->notify_group_ids);
			}

			if (!$data->id)
			{
				// New category, set layout to default
				$data->category_layout = 'default';
				$data->documents_layout = 2;
			}
			$data->groups = [];
			if($data->id > 0) 
			{
                $groups = EDocmanHelper::getGroupLevels(0, $data->id);
                if($groups != '')
				{
                    $data->groups = explode(",",$groups);
                }
            }

			
			$group_ids = $this->data->owner_group_ids;
			if($group_ids != "")
			{
				$tempGroupIds		   = [];
				$this->data->group_ids = [];
				$group_ids = explode(",",$group_ids);
				foreach($group_ids as $gid)
				{
					$temp				= new \stdClass();
					$temp->value		= $gid;
					$tempGroupIds[]	    = $temp;
				}
				$this->data->group_ids = $tempGroupIds;
			}
			

			$this->data = $data;
		}

		return $this->data;
	}
}
