<?php
/**
 * Copyright 2005-2017 de Solis Soluções Livres Ltda.
 *
 * Este arquivo é parte do programa Gnuteca.
 *
 * O Gnuteca é um software de propriedade da SOLIS, sendo desenvolvido
 * e mantido exclusivamente por esta empresa.
 *
 * A licença de uso está disponível mediante aquisição exclusiva junto à
 * SOLIS. A licença é concedida sem caráter de exclusividade ao licenciado.
 * Os direitos de uso são perpétuos.
 *
 * Embora os códigos fontes sejam fornecidos, o software é de propriedade
 * da SOLIS, não sendo permitido ao adquirente da licença a sua revenda,
 * empréstimo ou cessão (onerosa ou não) à terceiros. Também não é permitido,
 * a qualquer título e tempo, promover no software qualquer tipo de alienação,
 * reprodução, distribuição, divulgação, registro, licenciamento, transferência
 * ou qualquer outro ato que prejudique ou comprometa os direitos de propriedade
 * de software, o nome e a imagem da sua proprietária e do próprio software,
 * além de configurar concorrência à SOLIS.
 *
 * O licenciado, com o acesso ao código fonte do software, terá o direito de
 * promover mudanças no respectivo código. No entanto, nas situações em que ele
 * contar com o suporte oficial prestado pela SOLIS, não poderá promover mudanças
 * no código fonte, sob pena de perda do referido suporte.
 *
 * Para conhecer em detalhes o Termo de Licenciamento do Software Gnuteca
 * leia o arquivo “LICENCA.txt” disponível junto ao código deste software.
 * 
 * 
 *
 *
 *
 * 
 *
 **/

include("GnutecaWebServices.class.php");

class gnuteca3WebServicesPurchaseRequest extends GWebServices
{
    
    /**
     * Attributes
     */
    private $busPurchaseRequest;
    private $busPurchaseRequestMaterial;

    /**
     * Contructor method
     */
    public function __construct()
    {
        parent::__construct();
        $this->busPurchaseRequest = $this->MIOLO->getBusiness($this->module, 'BusPurchaseRequest');
        $this->busPurchaseRequestMaterial = $this->MIOLO->getBusiness($this->module, 'BusPurchaseRequestMaterial');
    }
    
    /**
     * Obtém informações dos exemplares referentes aos números de solicitações de compra. 
     *
     * @param (int) $clientId
     * @param (String) $clientPassword base64 encoded
     * @param (Array) $solicitacoesDeCompra Array com todos os números de solicitação de compras
     * 
     * @return (Array) Retorna um array de objetos contendo informações sobre os exemplares referentes aos números de solicitações de compras.
     * 
     */
    public function getExemplariesFromPurchaseRequest($clientId, $clientPassword, $solicitacoesDeCompra = array())
    {
        // CHECA ACESSO AO METHODO
        parent::__setClient($clientId, $clientPassword);
        if(!parent::__checkMethod('getExemplariesFromPurchaseRequest', false))
        {
            return parent::__getErrorStr();
        }
        
        return $this->busPurchaseRequest->getExemplariesFromPurchaseRequest($solicitacoesDeCompra);
    }

    /**
     * Webservice para listar as sugestões de materiais de um usuário
     * @param int $clientId
     * @param string $clientPassword
     * @param int $personId
     * @param int $purchaserequestId
     * @param int $libraryUnitId
     * @param string $observation
     * @param int $statusId
     * @return bool|string
     */
    public function listPurchaseRequest(
        $clientId,
        $clientPassword,
        $personId,
        $purchaseRequestId = null,
        $libraryUnitId = null,
        $observation = null,
        $statusId = null,
        array $searchableFields,
        $pageNumber = 1
    ) {
        $retorno = new stdClass();
        
        parent::__setClient($clientId, $clientPassword);
        if(!parent::__checkMethod('listPurchaseRequest', false))
        {
            return parent::__getErrorStr();
        }
        
        // Se as variáveis forem nulas, não serão consideradas na consulta pelo BusPruchaseRequest com exceção do personId
        $this->busPurchaseRequest->personIdS = $personId;
        $this->busPurchaseRequest->observationS = $observation;
        $this->busPurchaseRequest->workflowStatusS = $statusId;
        $this->busPurchaseRequest->libraryUnitIdS = $libraryUnitId;
        $this->busPurchaseRequest->purchaseRequestIdS = $purchaseRequestId;

        // Particiona o retorno da consulta com base no número de registros por página
        $purchaseRequests = array_chunk($this->listPurchaseRequestData($searchableFields), LISTING_NREGS);
        
        if (empty($purchaseRequests)) 
        {
            $retorno->message = "Nenhuma sugestão econtrada";
            return json_encode($retorno);
        }

        // Obtém apenas os registros de uma determinada página
        foreach ($purchaseRequests[$pageNumber - 1] as $purchaseRequest)
        {
            $authorData = $this->busPurchaseRequestMaterial->getPurchaseRequestMaterial($purchaseRequest->purchaseRequestId, '100', 'a');
            $titleData =  $this->busPurchaseRequestMaterial->getPurchaseRequestMaterial($purchaseRequest->purchaseRequestId, '245', 'a');
            $retorno->purchaseRequest[] = [
                "purchaseRequestId" => $purchaseRequest->purchaseRequestId,
                "title" => $titleData->content,
                "author" => $authorData->content,
                "libraryUnit" => $purchaseRequest->libraryname,
                "observation" => $purchaseRequest->observation ?? '-',
                "statusId" => $purchaseRequest->name ?? '-',
                "teste" => $purchaseRequest->total_linhas
            ];
        }
        
        // Dados de retorno
        $retorno->numberOfPages = count($purchaseRequests);

        return json_encode($retorno);
    }

    private function listPurchaseRequestData($searchableFields)
    {

        // Se não há parâmetros relevantes, retorna direto
        if (!$searchableFields) 
        {
            return $this->busPurchaseRequest->searchPurchaseRequest('purchaseRequestId desc', true);
        }

        $dinamicFields = self::formatDinamicFields($searchableFields);

        $newData = new stdClass();
        $newData->dinamicFields = $dinamicFields;

        $this->busPurchaseRequest->setData($newData);

        return $this->busPurchaseRequest->searchPurchaseRequest('purchaseRequestId desc', true);
    }

    /**
     * Formata os campos marc passados
     * @example transforma 245_a para 245.a
     */
    private static function formatDinamicFields(array $fields)
    {
        $mappedFields = array_map(function ($index, $value) {
            $key = str_replace('_', '.', $index);
            return [$key => $value];
        }, array_keys($fields), array_values($fields));

        return array_merge(...$mappedFields);
    }

    /**
     * Webservice para inserir uma sugestão de material de um usuário
     * @param int $clientId
     * @param string $clientPassword
     * @param int $personId
     * @param int $libraryUnitId
     * @param int $amount
     * @param string $course
     * @param string $title
     * @param string $author
     * @param string $publisher
     * @param string $edition
     * @param string $volume
     * @param string $observation
     * @return bool|string
     */
    public function insertPurchaseRequest(
        $clientId,
        $clientPassword,
        $personId,
        $course,
        $libraryUnitId,
        $amount,
        $observation,
        array $inputFields
    ) {

        $retorno = new stdClass();

        parent::__setClient($clientId, $clientPassword);
        if(!parent::__checkMethod('insertPurchaseRequest', false))
        {
            return parent::__getErrorStr();
        }

        $this->busPurchaseRequest->personId = $personId;
        $this->busPurchaseRequest->course = $course;
        $this->busPurchaseRequest->libraryUnitId = $libraryUnitId;
        $this->busPurchaseRequest->amount = $amount;
        $this->busPurchaseRequest->observation = $observation;
        $this->busPurchaseRequest->dinamicFields = self::formatDinamicFields($inputFields); 
        $retorno->return = $this->busPurchaseRequest->insertPurchaseRequest();

        if ($retorno->return)
        {
            $retorno->message = 'Sugestão de livro inserida com sucesso!';
            return json_encode($retorno); 
        }

        $retorno->message = 'Erro ao inserir sugestão de livro.';
        return json_encode($retorno);
    }

    /**
     * Lista inputs para os campos do parâmetro FIELDS_PURCHASE_REQUEST
     */
    public function listPurchaseRequestInputFields($clientId, $clientPassword) {
        $retorno = new stdClass();
        
        parent::__setClient($clientId, $clientPassword);
        if(!parent::__checkMethod('listPurchaseRequestInputFields', false))
        {
            return parent::__getErrorStr();
        }

        if (empty(trim(FIELDS_PURCHASE_REQUEST))) 
        {
            return false;
        }

        $fields = $this->busPurchaseRequest->parseFieldsPurchaseRequest();

        $formattedFields = array_map(function ($e) {
            return [
              "field" => $e->id,
              "label" => $e->label,
              "placeholder" => $e->hint,
              "required" => $e->required == 't' ? true : false,
              "searchable" => $e->searchable == 't' ? true : false,
            ];
        }, $fields);

        $retorno->fields = $formattedFields;
        return json_encode($retorno);
    }

    /**
     * Lista os estados possíveis para a sugestão de material
     * @param int $clientId
     * @param string $clientPassword
     */
    public function listPurchaseRequestStatus($clientId, $clientPassword) {
        $retorno = new stdClass();

        parent::__setClient($clientId, $clientPassword);
        if(!parent::__checkMethod('listPurchaseRequestStatus', false))
        {
            return parent::__getErrorStr();
        }

        $busWorkflowStatus = $this->MIOLO->getBusiness("gnuteca3", "BusWorkflowStatus");
        $busWorkflowStatus->workflowId = 'PURCHASE_REQUEST';
        $status = $busWorkflowStatus->searchWorkflowStatus(true);
        $status[] = [
            "workflowStatusId" => "",
            "workflowId" => "PURCHASE_REQUEST",
            "name" => "Todos estados",
            ""
        ];

        // Ordena em ordem crescente pelo workflowStatusId colocando o "Todos estados" em primeiro
        usort($status, function($a, $b) {
            if ($a->workflowStatusId === "") return -1;
            if ($b->workflowStatusId === "") return 1;
            return (string) $a->workflowStatusId - (string)$b->workflowStatusId;
        });

        $retorno->workflowStatus = $status;

        return json_encode($retorno);
    }

    /**
     * Lista todas unidades de biblioteca que aceitam sujestão de compras e que o usuário possui permissão
     */
    public function listUserPurchaseRequestLibraryUnities($clientId, $clientPassword, $personId) {
        $retorno = new stdClass();

        parent::__setClient($clientId, $clientPassword);
        if(!parent::__checkMethod('listUserPurchaseRequestLibraryUnities', false))
        {
            return parent::__getErrorStr();
        }

        $busLibraryUnit = $this->MIOLO->getBusiness("gnuteca3", "BusLibraryUnit");

        // O método não retorna um objeto por padrão, 0 = libraryUnitId e 1 = libraryName
        $userLibraryUnities = $busLibraryUnit->listListLibraryUnitAcceptingPurchaseRequest($personId);

        $retorno = array_map(function ($item) {
            return [
                "libraryUnitId" => $item[0],
                "description" => $item[1]
            ];
        }, $userLibraryUnities);
        
        return json_encode($retorno);
    }
}