<?php

/**
 * OpenKM, Open Knowledge Management System S.L.  (http://www.openkm.com)
 * Copyright (c) 2006-2018
 *
 * No bytes were intentionally harmed during the development of this application.
 *
 * This program is commercial software; you can use it under the terms of the
 * EULA - OpenKM SDK End User License Agreement as published by OpenKM Knowledge Management System S.L.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * EULA - OpenKM SDK End User License Agreement for more details:
 * http://docs.openkm.com/kcenter/view/licenses/eula-openkm-sdk-end-user-license-agreement.html
 */

namespace openkm\impl;

use openkm\bean\SimplePropertyGroup;
use openkm\definition\BasePropertyGroup;
use openkm\util\UriHelper;
use openkm\util\BeanHelper;
use Httpful\Request;
use Httpful\Mime;
use openkm\util\Status;
use openkm\util\TypeException;
use openkm\exception\AccessDeniedException;
use openkm\exception\PathNotFoundException;
use openkm\exception\RepositoryException;
use openkm\exception\DatabaseException;
use Httpful\Exception\ConnectionErrorException;
use openkm\exception\UnknowException;
use openkm\exception\ExtensionException;
use openkm\exception\AutomationException;
use openkm\exception\LockException;
use openkm\exception\IOException;
use openkm\exception\ParseException;
use openkm\exception\NoSuchGroupException;
use openkm\exception\NoSuchPropertyException;
use openkm\exception\SuggestionException;
use openkm\exception\PluginNotFoundException;
use openkm\util\FormatUtils;
use openkm\bean\AddPropertyGroupParams;

/**
 * PropertyGroupImpl
 *
 * @author sochoa
 */
class PropertyGroupImpl extends ClientImpl implements BasePropertyGroup {

    /**
     * Add an empty metadata group to a node
     *
     * @param string $uuid The uuid or path of the document, folder, mail or record
     * @param string $grpName The grpName should be a valid Metadata group name.
     * @param array $properties An array of the SimplePropertyGroup
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws LockException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws ExtensionException
     * @throws AutomationException
     * @throws UnknowException
     */
    public function addPropertyGroup($uuid, $grpName, $properties = []) {
        try {
            $uri = UriHelper::getUri($this->host, FormatUtils::format(UriHelper::PROPERTY_GROUP_POST_ADD_GROUP, ['uuid' => $uuid]));

            $params = new AddPropertyGroupParams();
            $params->setGrpName($grpName);
            $params->setProperties(BeanHelper::copyToGroupPropertyList($properties));

            $client = Request::post($uri);
            $response = $this->getClientWithBody($client, $params);

            if ($response->code != Status::OK) {
                $restException = new \openkm\bean\RestException();
                $restException = $this->phpRestException($response->body);
                if ($restException->getSimpleName() != '') {
                    if ($restException->getSimpleName() == TypeException::LOCK_EXCEPTION) {
                        throw new LockException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                        throw new PathNotFoundException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::REPOSITORY_EXCEPTION) {
                        throw new RepositoryException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::DATABASE_EXCEPTION) {
                        throw new DatabaseException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::EXTENSION_EXCEPTION) {
                        throw new ExtensionException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::AUTOMATION_EXCEPTION) {
                        throw new AutomationException($restException->getMessage());
                    } else {
                        throw new UnknowException($restException->getMessage());
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Remove a metadata group of a node.
     *
     * @param string $uuid The uuid or path of the document, folder, mail or record
     * @param string $grpName The grpName should be a valid Metadata group name.
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws NoSuchGroupException
     * @throws PathNotFoundException
     * @throws LockException
     * @throws DatabaseException
     * @throws RepositoryException
     * @throws ExtensionException
     * @throws UnknowException
     */
    public function removePropertyGroup($uuid, $grpName) {
        try {
            $uri = UriHelper::getUri($this->host, FormatUtils::format(UriHelper::PROPERTY_GROUP_DEL_REMOVE_GROUP, ['uuid' => $uuid, 'grpName' => $grpName]));
            $client = Request::delete($uri);
            $response = $this->getClient($client);
            if ($response->code != Status::OK) {
                $restException = new \openkm\bean\RestException();
                $restException = $this->phpRestException($response->body);
                if ($restException->getSimpleName() != '') {
                    if ($restException->getSimpleName() == TypeException::NO_SUCH_GROUP_EXCEPTION) {
                        throw new NoSuchGroupException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                        throw new PathNotFoundException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::LOCK_EXCEPTION) {
                        throw new LockException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::DATABASE_EXCEPTION) {
                        throw new DatabaseException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::REPOSITORY_EXCEPTION) {
                        throw new RepositoryException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::EXTENSION_EXCEPTION) {
                        throw new ExtensionException($restException->getMessage());
                    } else {
                        throw new UnknowException($restException->getMessage());
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Get Groups
     *
     * @param string $uuid The uuid or path of the document, folder, mail or record
     * @return array(PropertyGroup) Retrieve a list of metadata groups assigned to a node.
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws IOException
     * @throws PathNotFoundException
     * @throws ParseException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function getPropertyGroups($uuid) {
        try {
            $uri = UriHelper::getUri($this->host, FormatUtils::format(UriHelper::PROPERTY_GROUP_GET_GROUPS, ['uuid' => $uuid]));
            $client = Request::get($uri);
            $response = $this->getClient($client);
            if ($response->code == Status::OK) {
                $propertyGroups = [];
                foreach ($response->body as $propertyGroupJson) {
                    $propertyGroups[] = $this->phpPropertyGroup($propertyGroupJson);
                }
                return $propertyGroups;
            } else {
                $restException = new \openkm\bean\RestException();
                $restException = $this->phpRestException($response->body);
                if ($restException->getSimpleName() != '') {
                    if ($restException->getSimpleName() == TypeException::IO_EXCEPTION) {
                        throw new IOException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                        throw new PathNotFoundException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::PARSE_EXCEPTION) {
                        throw new ParseException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::REPOSITORY_EXCEPTION) {
                        throw new RepositoryException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::DATABASE_EXCEPTION) {
                        throw new DatabaseException($restException->getMessage());
                    } else {
                        throw new UnknowException($restException->getMessage());
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Get all groups
     *
     * @return array(PropertyGroup) Retrieve a list of all metadata groups set into the application.
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws IOException
     * @throws ParseException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function getAllPropertyGroups() {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::PROPERTY_GROUP_GET_ALL_GROUPS);
            $client = Request::get($uri);
            $response = $this->getClient($client);
            if ($response->code == Status::OK) {
                $propertyGroups = [];
                foreach ($response->body as $propertyGroupJson) {
                    $propertyGroups[] = $this->phpPropertyGroup($propertyGroupJson);
                }
                return $propertyGroups;
            } else {
                $restException = new \openkm\bean\RestException();
                $restException = $this->phpRestException($response->body);
                if ($restException->getSimpleName() != '') {
                    if ($error == TypeException::IO_EXCEPTION) {
                        throw new IOException($restException->getMessage());
                    } else if ($error == TypeException::PARSE_EXCEPTION) {
                        throw new ParseException($restException->getMessage());
                    } else if ($error == TypeException::REPOSITORY_EXCEPTION) {
                        throw new RepositoryException($restException->getMessage());
                    } else if ($error == TypeException::DATABASE_EXCEPTION) {
                        throw new DatabaseException($restException->getMessage());
                    } else {
                        throw new UnknowException($restException->getMessage());
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Get Property Group Form
     *
     * The method is usually used to display empty form elements for creating new metadata values.
     *
     * @param string $grpName The grpName should be a valid Metadata group name.
     * @return array(FormElement) Retrieve a list of all metadata group elements and its values of a node.
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws IOException
     * @throws ParseException
     * @throws NoSuchGroupException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function getPropertyGroupForm($grpName) {
        try {
            $uri = UriHelper::getUri($this->host, FormatUtils::format(UriHelper::PROPERTY_GROUP_GET_PROPERTY_GROUP_FORM, ['grpName' => $grpName]));
            $client = Request::get($uri);
            $response = $this->getClient($client);
            if ($response->code == Status::OK) {
                $formElements = [];
                foreach ($response->body as $formElementComplexJson) {
                    $formElements[] = BeanHelper::copyToFormElement($this->phpFormElementComplex($formElementComplexJson));
                }
                return $formElements;
            } else {
                $restException = new \openkm\bean\RestException();
                $restException = $this->phpRestException($response->body);
                if ($restException->getSimpleName() != '') {
                    if ($restException->getSimpleName() == TypeException::IO_EXCEPTION) {
                        throw new IOException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::PARSE_EXCEPTION) {
                        throw new ParseException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::NO_SUCH_GROUP_EXCEPTION) {
                        throw new NoSuchGroupException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                        throw new PathNotFoundException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::REPOSITORY_EXCEPTION) {
                        throw new RepositoryException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::DATABASE_EXCEPTION) {
                        throw new DatabaseException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::PLUGIN_NOT_FOUND_EXCEPTION) {
                        throw new PluginNotFoundException($restException->getMessage());
                    } else {
                        throw new UnknowException($restException->getMessage());
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    public function getPropertyGroupFormByNode($uuid, $grpName) {
        try {
            $uri = UriHelper::getUri($this->host, FormatUtils::format(UriHelper::PROPERTY_GROUP_GET_PROPERTY_GROUP_FORM_BY_NODE, ['uuid' => $uuid, 'grpName' => $grpName]));
            $client = Request::get($uri);
            $response = $this->getClient($client);
            if ($response->code == Status::OK) {
                $formElements = [];
                foreach ($response->body as $formElementComplexJson) {
                    $formElements[] = BeanHelper::copyToFormElement($this->phpFormElementComplex($formElementComplexJson));
                }
                return $formElements;
            } else {
                $restException = new \openkm\bean\RestException();
                $restException = $this->phpRestException($response->body);
                if ($restException->getSimpleName() != '') {
                    if ($restException->getSimpleName() == TypeException::IO_EXCEPTION) {
                        throw new IOException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::PARSE_EXCEPTION) {
                        throw new ParseException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::NO_SUCH_GROUP_EXCEPTION) {
                        throw new NoSuchGroupException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                        throw new PathNotFoundException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::REPOSITORY_EXCEPTION) {
                        throw new RepositoryException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::DATABASE_EXCEPTION) {
                        throw new DatabaseException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::PLUGIN_NOT_FOUND_EXCEPTION) {
                        throw new PluginNotFoundException($restException->getMessage());
                    } else {
                        throw new UnknowException($restException->getMessage());
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Change the metadata group values of a node.
     *
     * Is not mandatory set into properties parameter all fields values, is enought with the fields you wish to change its values.
     *
     * @param string $uuid The uuid of the document, folder, mail or record
     * @param string $grpName The grpName should be a valid Metadata group name.
     * @param array $properties An array of the SimplePropertyGroup
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws IOException
     * @throws ParseException
     * @throws NoSuchPropertyException
     * @throws NoSuchGroupException
     * @throws LockException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws ExtensionException
     * @throws AutomationException
     * @throws UnknowException
     */
    public function setPropertyGroupProperties($uuid, $grpName, $properties = []) {
        try {
            $uri = UriHelper::getUri($this->host, FormatUtils::format(UriHelper::PROPERTY_GROUP_PUT_SET_PROPERTIES, ['uuid' => $uuid, 'grpName' => $grpName]));
            $client = Request::put($uri);
            $response = $this->getClientWithBody($client, BeanHelper::copyToGroupPropertyList($properties));
            if ($response->code != Status::OK) {
                $restException = new \openkm\bean\RestException();
                $restException = $this->phpRestException($response->body);
                if ($restException->getSimpleName() != '') {
                    if ($restException->getSimpleName() == TypeException::IO_EXCEPTION) {
                        throw new IOException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::PARSE_EXCEPTION) {
                        throw new ParseException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::NO_SUCH_PROPERTY_EXCEPTION) {
                        throw new NoSuchPropertyException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::NO_SUCH_GROUP_EXCEPTION) {
                        throw new NoSuchGroupException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::LOCK_EXCEPTION) {
                        throw new LockException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                        throw new PathNotFoundException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::REPOSITORY_EXCEPTION) {
                        throw new RepositoryException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::DATABASE_EXCEPTION) {
                        throw new DatabaseException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::EXTENSION_EXCEPTION) {
                        throw new ExtensionException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::AUTOMATION_EXCEPTION) {
                        throw new AutomationException($restException->getMessage());
                    } else {
                        throw new UnknowException($restException->getMessage());
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Has Group
     *
     * @param string $uuid The uuid of the document, folder, mail or record
     * @param string $grpName The grpName should be a valid Metadata group name.
     * @return bool Return a boolean that indicate if the node has or not a metadata group.
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws IOException
     * @throws ParseException
     * @throws NoSuchGroupException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function hasPropertyGroup($uuid, $grpName) {
        try {
            $uri = UriHelper::getUri($this->host, FormatUtils::format(UriHelper::PROPERTY_GROUP_GET_HAS_GROUP, ['uuid' => $uuid, 'grpName' => $grpName]));
            $client = Request::get($uri);
            $response = $this->getClientWithHTMLResponse($client);
            if ($response->code == Status::OK) {
                return boolval($response->body);
            } else {
                $restException = new \openkm\bean\RestException();
                $restException = $this->phpRestException($response->body);
                if ($restException->getSimpleName() != '') {
                    if ($restException->getSimpleName() == TypeException::REPOSITORY_EXCEPTION) {
                        throw new RepositoryException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                        throw new PathNotFoundException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::DATABASE_EXCEPTION) {
                        throw new DatabaseException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::IO_EXCEPTION) {
                        throw new IOException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::PARSE_EXCEPTION) {
                        throw new ParseException($restException->getMessage());
                    } else {
                        throw new UnknowException($restException->getMessage());
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    public function getPropertyGroupsByVersion($uuid, $versionName) {
        try {
            $uri = UriHelper::getUri($this->host, FormatUtils::format(UriHelper::PROPERTY_GROUP_GET_GROUPS_BY_VERSION, ['uuid' => $uuid, 'versionName' => $versionName]));
            $client = Request::get($uri);
            $response = $this->getClient($client);
            if ($response->code == Status::OK) {
                $propertyGroups = [];
                foreach ($response->body as $propertyGroupJson) {
                    $propertyGroups[] = $this->phpPropertyGroup($propertyGroupJson);
                }
                return $propertyGroups;
            } else {
                $restException = new \openkm\bean\RestException();
                $restException = $this->phpRestException($response->body);
                if ($restException->getSimpleName() != '') {
                    if ($restException->getSimpleName() == TypeException::IO_EXCEPTION) {
                        throw new IOException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::PARSE_EXCEPTION) {
                        throw new ParseException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::NO_SUCH_GROUP_EXCEPTION) {
                        throw new NoSuchGroupException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                        throw new PathNotFoundException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::REPOSITORY_EXCEPTION) {
                        throw new RepositoryException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::DATABASE_EXCEPTION) {
                        throw new DatabaseException($restException->getMessage());
                    } else {
                        throw new UnknowException($restException->getMessage());
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Get Registered Definition
     *
     * The method only can be executed by super user grants ( ROLE_ADMIN member user).
     *
     * @return string Return the XML Metada groups definition.
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws IOException
     * @throws ParseException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function getRegisteredPropertyGroupDefinition() {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::PROPERTY_GROUP_GET_REGISTERED_DEFINITION);
            $client = Request::get($uri);
            $response = $this->getClientWithHTMLResponse($client);
            if ($response->code == Status::OK) {
                return (string) $response->body;
            } else {
                $restException = new \openkm\bean\RestException();
                $restException = $this->phpRestException($response->body);
                if ($restException->getSimpleName() != '') {
                    if ($restException->getSimpleName() == TypeException::IO_EXCEPTION) {
                        throw new IOException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::PARSE_EXCEPTION) {
                        throw new ParseException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::DATABASE_EXCEPTION) {
                        throw new DatabaseException($restException->getMessage());
                    } else {
                        throw new UnknowException($restException->getMessage());
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Get Suggestions
     *
     * More information at Creating your own Suggestion Analyzer plugin and Metadata Select field.
     *
     * @param string $uuid The uuid of the document, folder, mail or record
     * @param string $grpName The grpName should be a valid Metadata group name.
     * @param string $propName The grpName should be a valid Metadata group name.
     * @return array Retrieve a list of a suggested metadata field values.
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws PathNotFoundException
     * @throws DatabaseException
     * @throws IOException
     * @throws ParseException
     * @throws NoSuchGroupException
     * @throws SuggestionException
     * @throws UnknowException
     */
    public function getPropertyGroupSuggestions($uuid, $grpName, $propName) {
        try {
            $uri = UriHelper::getUri($this->host, FormatUtils::format(UriHelper::PROPERTY_GROUP_GET_SUGGESTIONS, ['uuid' => $uuid]));
            $uri .= '?grpName=' . urlencode($grpName) . '&propName=' . urlencode($propName);

            $client = Request::get($uri);
            $response = $this->getClient($client);

            if ($response->code == Status::OK) {
                $suggestions = [];
                foreach ($response->body as $suggestionJson) {
                    $suggestions[] = (string) $suggestionJson;
                }
                return $suggestions;
            } else {
                $restException = new \openkm\bean\RestException();
                $restException = $this->phpRestException($response->body);
                if ($restException->getSimpleName() != '') {
                    if ($restException->getSimpleName() == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                        throw new PathNotFoundException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::DATABASE_EXCEPTION) {
                        throw new DatabaseException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::IO_EXCEPTION) {
                        throw new IOException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::PARSE_EXCEPTION) {
                        throw new ParseException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::NO_SUCH_GROUP_EXCEPTION) {
                        throw new NoSuchGroupException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::SUGGESTION_EXCEPTION) {
                        throw new SuggestionException($restException->getMessage());
                    } else {
                        throw new UnknowException($restException->getMessage());
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Set the XML Metada groups definition into the repository
     *
     * The method only can be executed by super user grants ( ROLE_ADMIN member user).
     *
     * @param string $content Recommend using file_get_contents — Reads entire file into a string
     * @param string $name The name is metadata 
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws IOException
     * @throws ParseException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function registerPropertyGroupDefinition($content, $name) {
        try {
            $uri = UriHelper::getUri($this->host, UriHelper::PROPERTY_GROUP_POST_REGISTER_DEFINITION);

            $params = [];
            $param1 = [];
            $param1['name'] = 'pgName';
            $param1['body'] = $name;
            $params[] = $param1;

            $files = [];
            $file['name'] = 'content';
            $file['body'] = $content;
            $file['fileName'] = '';
            $files[] = $file;

            $body = [];
            $body['params'] = $params;
            $body['files'] = $files;

            $client = Request::post($uri);
            $client->setCurlPostFile(true);
            $client->sends(Mime::UPLOAD);
            $client->body($body);
            $client->addHeader('Authorization', $this->authorizationToken);
            $client->expects(Mime::JSON);

            $response = $client->send();

            if ($response->code != Status::OK) {
                $restException = new \openkm\bean\RestException();
                $restException = $this->phpRestException($response->body);
                if ($restException->getSimpleName() != '') {
                    if ($restException->getSimpleName() == TypeException::IO_EXCEPTION) {
                        throw new IOException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::PARSE_EXCEPTION) {
                        throw new ParseException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::DATABASE_EXCEPTION) {
                        throw new DatabaseException($restException->getMessage());
                    } else {
                        throw new UnknowException($restException->getMessage());
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    /**
     * Get Property Group Properties
     *
     * @param string $uuid The uuid of the document, folder, mail or record
     * @param string $grpName The grpName should be a valid Metadata group name.
     * @return array Retrieve a list of all metadata group elements and its values of a node.
     * @throws ConnectionErrorException
     * @throws AccessDeniedException
     * @throws IOException
     * @throws ParseException
     * @throws NoSuchGroupException
     * @throws PathNotFoundException
     * @throws RepositoryException
     * @throws DatabaseException
     * @throws UnknowException
     */
    public function getPropertyGroupProperties($uuid, $grpName) {
        try {
            $uri = UriHelper::getUri($this->host, FormatUtils::format(UriHelper::PROPERTY_GROUP_GET_PROPERTIES, ['uuid' => $uuid, 'grpName' => $grpName]));
            $client = Request::get($uri);
            $response = $this->getClient($client);
            if ($response->code == Status::OK) {
                $properties = [];
                foreach ($response->body as $simplePropertyGroupJson) {
                    $simplePropertyGroup = $this->phpSimplePropertyGroup($simplePropertyGroupJson);
                    $properties[$simplePropertyGroup->getName()] = $simplePropertyGroup->getValue();
                }
                return $properties;
            } else {
                $restException = new \openkm\bean\RestException();
                $restException = $this->phpRestException($response->body);
                if ($restException->getSimpleName() != '') {
                    if ($restException->getSimpleName() == TypeException::IO_EXCEPTION) {
                        throw new IOException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::PARSE_EXCEPTION) {
                        throw new ParseException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::NO_SUCH_GROUP_EXCEPTION) {
                        throw new NoSuchGroupException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                        throw new PathNotFoundException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::REPOSITORY_EXCEPTION) {
                        throw new RepositoryException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::DATABASE_EXCEPTION) {
                        throw new DatabaseException($restException->getMessage());
                    } else {
                        throw new UnknowException($restException->getMessage());
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    public function getPropertyGroupPropertiesByVersion($uuid, $grpName, $versionName) {
        try {
            $uri = UriHelper::getUri($this->host, FormatUtils::format(UriHelper::PROPERTY_GROUP_GET_PROPERTIES_BY_VERSION, ['uuid' => $uuid, 'versionName' => $versionName, 'grpName' => $grpName,]));
            $client = Request::get($uri);
            $response = $this->getClient($client);
            if ($response->code == Status::OK) {
                $properties = [];
                foreach ($response->body as $simplePropertyGroupJson) {
                    $simplePropertyGroup = $this->phpSimplePropertyGroup($simplePropertyGroupJson);
                    $properties[$simplePropertyGroup->getName()] = $simplePropertyGroup->getValue();
                }
                return $properties;
            } else {
                $restException = new \openkm\bean\RestException();
                $restException = $this->phpRestException($response->body);
                if ($restException->getSimpleName() != '') {
                    if ($error == TypeException::IO_EXCEPTION) {
                        throw new IOException($error . ': ' . $msg);
                    } else if ($error == TypeException::PARSE_EXCEPTION) {
                        throw new ParseException($error . ': ' . $msg);
                    } else if ($error == TypeException::NO_SUCH_GROUP_EXCEPTION) {
                        throw new NoSuchGroupException($error . ': ' . $msg);
                    } else if ($error == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                        throw new PathNotFoundException($error . ': ' . $msg);
                    } else if ($error == TypeException::REPOSITORY_EXCEPTION) {
                        throw new RepositoryException($error . ': ' . $msg);
                    } else if ($error == TypeException::DATABASE_EXCEPTION) {
                        throw new DatabaseException($error . ': ' . $msg);
                    } else {
                        throw new UnknowException($error . ': ' . $msg);
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    public function getPropertyGroupByVersionForm($uuid, $grpName, $versionName) {
        try {
            $uri = UriHelper::getUri($this->host, FormatUtils::format(UriHelper::PROPERTY_GROUP_GET_PROPERTIES_BY_VERSION_FORM, ['uuid' => $uuid, 'grpName' => $grpName, 'versionName' => $versionName]));
            $client = Request::get($uri);
            $response = $this->getClient($client);
            if ($response->code == Status::OK) {
                $formElements = [];
                foreach ($response->body as $formElementComplexJson) {
                    $formElements[] = BeanHelper::copyToFormElement($this->phpFormElementComplex($formElementComplexJson));
                }
                return $formElements;
            } else {
                $restException = new \openkm\bean\RestException();
                $restException = $this->phpRestException($response->body);
                if ($restException->getSimpleName() != '') {
                    if ($restException->getSimpleName() == TypeException::IO_EXCEPTION) {
                        throw new IOException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::PARSE_EXCEPTION) {
                        throw new ParseException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::NO_SUCH_GROUP_EXCEPTION) {
                        throw new NoSuchGroupException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                        throw new PathNotFoundException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::REPOSITORY_EXCEPTION) {
                        throw new RepositoryException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::DATABASE_EXCEPTION) {
                        throw new DatabaseException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::PLUGIN_NOT_FOUND_EXCEPTION) {
                        throw new PluginNotFoundException($restException->getMessage());
                    } else {
                        throw new UnknowException($restException->getMessage());
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

    public function getPropertyGroup($grpName) {
        try {
            $uri = UriHelper::getUri($this->host, FormatUtils::format(UriHelper::PROPERTY_GROUP_GET_GROUP, ['grpName' => $grpName]));
            $client = Request::get($uri);
            $response = $this->getClient($client);
            if ($response->code == Status::OK) {
                return $this->phpPropertyGroup($response->body);
            } else {
                $restException = new \openkm\bean\RestException();
                $restException = $this->phpRestException($response->body);
                if ($restException->getSimpleName() != '') {
                    if ($restException->getSimpleName() == TypeException::IO_EXCEPTION) {
                        throw new IOException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::PARSE_EXCEPTION) {
                        throw new ParseException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::NO_SUCH_GROUP_EXCEPTION) {
                        throw new NoSuchGroupException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::PATH_NOT_FOUND_EXCEPTION) {
                        throw new PathNotFoundException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::REPOSITORY_EXCEPTION) {
                        throw new RepositoryException($restException->getMessage());
                    } else if ($restException->getSimpleName() == TypeException::DATABASE_EXCEPTION) {
                        throw new DatabaseException($restException->getMessage());
                    } else {
                        throw new UnknowException($restException->getMessage());
                    }
                } else {
                    throw new UnknowException("HTTP error code " . $response->code . ": " . $response->body);
                }
            }
        } catch (ConnectionErrorException $cee) {
            throw new ConnectionErrorException('ConnectionErrorException: ' . $cee->getMessage());
        }
    }

}

?>
