<?PHP

/**
 * Class used to add additional functionality to the FolderFactory class.
 */
class Folders_FolderFactory extends FolderFactory
{

    /**
     * @const string RESOURCE_FOLDER_NAME name given to root resource folders
     */
    const RESOURCE_FOLDER_NAME = "ResourceFolderRoot";

    /**
     * @const string DEFAULT_FOLDER_NAME name given to the default folder for
     *   resources created when no other folders exist
     */
    const DEFAULT_FOLDER_NAME = "Main Folder";

    /**
     * Save the owner ID if given and call the parent construtor.
     * @param mixed $OwnerId owner ID (optional)
     * @return void
     */
    public function __construct($OwnerId=NULL)
    {
        if (!is_null($OwnerId))
        {
            $this->OwnerId = intval($OwnerId);
        }

        parent::FolderFactory($OwnerId);
    }

    /**
     * Get the resource folder for the selected owner. Creates one if one does
     * not already exist.
     * @param mixed $OwnerId owner ID (optional); uses data member if not set
     * @return Folder resource folder object
     * @throws Exception if no owner ID is available
     */
    public function GetResourceFolder($OwnerId=NULL)
    {
        # throws exception if it cannot get the owner ID
        $OwnerId = $this->GetOwnerId($OwnerId);

        $Folder = $this->_GetResourceFolder($OwnerId);

        # folder already exists so just return it
        if ($Folder instanceof Folder)
        {
            return $Folder;
        }

        # create the folder and return it
        return $this->CreateResourceFolder($OwnerId);
    }

    /**
     * Create the resource folder for the given user. Won't create a new folder
     * if one already exists.
     * @param mixed $OwnerId owner ID (optional); uses data member if not set
     * @return Folder resource folder object
     * @throws Exception if no owner ID is available
     */
    public function CreateResourceFolder($OwnerId=NULL)
    {
        # throws exception if it cannot get the owner ID
        $OwnerId = $this->GetOwnerId($OwnerId);

        $Folder = $this->_GetResourceFolder($OwnerId);

        # folder already exists so just return it
        if ($Folder instanceof Folder)
        {
            return $Folder;
        }

        # create the folder and return it
        return $this->CreateFolder(
            "Folder",
            self::RESOURCE_FOLDER_NAME,
            $OwnerId);
    }

    /**
     * Get the selected folder from the list of resource folders. Creates a new
     * folder and selects it if one is not already selected.
     * @param mixed $OwnerId owner ID (optional); uses data member if not set
     * @return Folder resource folder object
     * @throws Exception if no owner ID is available
     */
    public function GetSelectedFolder($OwnerId=NULL)
    {
        # throws exception if it cannot get the owner ID
        $OwnerId = $this->GetOwnerId($OwnerId);

        $FolderId = $this->DB->Query("
            SELECT * FROM Folders_SelectedFolders
            WHERE OwnerId = '".addslashes($OwnerId)."'",
            "FolderId");

        try
        {
            $ResourceFolder = $this->GetResourceFolder($OwnerId);
            $Folder = new Folders_Folder($FolderId);
            $FolderId = $Folder->Id();

            # everything checks out, so return the folder
            if ($ResourceFolder->ContainsItem($Folder->Id()))
            {
                return $Folder;
            }

            # the folder is not a resource folder or it does not belong to the
            # root resource folder (therefore, the user), so create a new
            # default folder and select it
            else
            {
                $NewFolder = $this->CreateDefaultFolder($OwnerId);
                $this->SelectFolder($NewFolder);

                return $NewFolder;
            }
        }

        # bad folder ID, create a new default folder and select it
        catch (Exception $Exception)
        {
            $NewFolder = $this->CreateDefaultFolder($OwnerId);
            $this->SelectFolder($NewFolder);

            return $NewFolder;
        }
    }

    /**
     * Select the given folder for the given owner ID.
     * @return Folder $Folder folder to select
     * @param mixed $OwnerId owner ID (optional); uses data member if not set
     * @return void
     * @throws Exception if no owner ID is available
     */
    public function SelectFolder(Folder $Folder, $OwnerId=NULL)
    {
        # throws exception if it cannot get the owner ID
        $OwnerId = $this->GetOwnerId($OwnerId);

        $ResourceFolder = $this->GetResourceFolder($OwnerId);

        # select only if the folder is a resource folder and it belongs to the
        # resource folder (therefore, the user)
        if ($ResourceFolder->ContainsItem($Folder->Id()))
        {
            # remove current selected folders for the user...
            $this->DB->Query("
                DELETE FROM Folders_SelectedFolders
                WHERE OwnerId = '".addslashes($OwnerId)."'");

            # ...and select the given one
            $this->DB->Query("
                INSERT INTO Folders_SelectedFolders
                (OwnerId, FolderId)
                VALUES
                ('".addslashes($OwnerId)."', '".addslashes($Folder->Id())."')");
        }
    }

    /**
     * Create a default folder and add it to the root resource folder.
     * @param mixed $OwnerId owner ID (optional); uses data member if not set
     * @return Folder folder object
     * @throws Exception if no owner ID is available
     */
    public function CreateDefaultFolder($OwnerId=NULL)
    {
        # throws exception if it cannot get the owner ID
        $OwnerId = $this->GetOwnerId($OwnerId);

        $DefaultFolder = $this->CreateFolder(
            "Resource",
            self::DEFAULT_FOLDER_NAME,
            $OwnerId);

        $ResourceFolder = $this->GetResourceFolder($OwnerId);
        $ResourceFolder->PrependItem($DefaultFolder->Id());

        return $DefaultFolder;
    }

    /**
     * Get an owner ID if available.
     * @param mixed $OwnerId owner ID (optional); uses data member if not set
     * @return mixed owner ID
     * @throws Exception if no owner ID is available
     */
    protected function GetOwnerId($OwnerId=NULL)
    {
        $OwnerId = !is_null($OwnerId) ? $OwnerId : $this->OwnerId;

        # need an owner ID to be able to get the resource folder
        if (!$OwnerId)
        {
            throw new Exception("No owner ID available");
        }

        return $OwnerId;
    }

    /**
     * Get the resource folder for the owner ID.
     * @param mixed $OwnerId owner ID
     * @return Folder|null folder object if found or NULL if one doesn't exist
     */
    protected function _GetResourceFolder($OwnerId)
    {
        $Folders = $this->GetFolders(
            "Folder",
            $OwnerId,
            self::RESOURCE_FOLDER_NAME);

        return count($Folders) ? array_shift($Folders) : NULL;
    }

    /**
     * @var int|null $OwnerId owner ID
     */
    protected $OwnerId;

}
