<?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 gnuteca3WebServicesSearch
{
    private $webService;
    private $MIOLO;

    public function __construct() {
        $this->webService = new GWebServices();
        $this->MIOLO = MIOLO::getInstance();
    }

    /**
     * Webservice de pesquisa
     * @param int $clientId
     * @param string $clientPassword
     * @param string $filter
     * @param int $libraryUnitId
     * @param int $pageNumber
     * @param string $termText
     * @return string|null JSON com os resultados da pesquisa
     */
    public function search(
        $clientId,
        $clientPassword,
        $filter,
        $termText,
        $libraryUnitId = null,
        $pageNumber = 1
    ) {
        $retorno = new stdClass();

        // Define acesso ao método e define a classe do Webservice
        $this->webService->__setClient($clientId, $clientPassword);
        $this->webService->setClassName(get_class($this));

        // Verifica se o usuário possui acesso ao WebService
        if (!$this->webService->__checkMethod("search", false))
        {
            $retorno->message = $this->webService->__getErrorStr();
            return json_encode($retorno);
        }

        $_REQUEST['pn_page'] = $pageNumber;
        $busGenericSearch = $this->MIOLO->getBusiness("gnuteca3", "BusGenericSearch2");

        // Ignorar planilhas
        if (strlen(SIMPLE_SEARCH_EXCLUDE_SPREEDSHET) > 0) 
        {
            $excludeSpreeshet = explode("\n", SIMPLE_SEARCH_EXCLUDE_SPREEDSHET); //tranformar em array separando por linha;

            if (is_array($excludeSpreeshet)) 
            {
                foreach ($excludeSpreeshet as $info) 
                {
                    $busGenericSearch->addMaterialControlWhere("categoryLevel", $info, 'AND', '!=');
                }
            }
        }

        // Ignorar status
        if (strlen(SIMPLE_SEARCH_EXCLUDE_EXEMPLARY_STATUS) > 0) 
        {
            $busGenericSearch->addExemplaryControlWhere(
                "IgnoreExemplaryStatusId",
                explode(",", SIMPLE_SEARCH_EXCLUDE_EXEMPLARY_STATUS),
                "AND",
                "NOT IN",
                TRUE
            );
        }

        // Filtros e se $libraryUnitId for null, busca exemplares em todas as unidades
        $busGenericSearch->addMaterialWhereByTag($filter, array($termText), 'AND', 'LIKE');
        if ($libraryUnitId) 
        {
            $busGenericSearch->addExemplaryControlWhere(
                array('libraryUnitId', 'originalLibraryUnitId'),
                $libraryUnitId,
                "AND",
                "IN",
                TRUE
            );
        }

        // Ordenação dos resultados
        $this->setOrderResult($busGenericSearch);

        // Executa a busca de dados
        $data = $busGenericSearch->getWorkSearch(null, true);

        $busSearchFormat = $this->MIOLO->getBusiness('gnuteca3', 'BusSearchFormat');
        $busMaterialControl = $this->MIOLO->getBusiness('gnuteca3', 'BusMaterialControl');
        $busExemplaryControl = $this->MIOLO->getBusiness('gnuteca3', 'BusExemplaryControl');

        foreach ($data as $line) 
        {
            // Formato de pesquisa
            $controlNumber = $line['CONTROLNUMBER'];
            $material = $busMaterialControl->getMaterialControl($controlNumber, true);
            // Exemplares
            $exemplaries = $busExemplaryControl->getExemplaryOfMaterial($controlNumber, null, true);

            // Cria o objeto
            $returnObj = new stdClass();
            $returnObj->controlNumber = $controlNumber;
            $returnObj->searchFormat = $busSearchFormat->formatSearchData(11, $line, null, $material->category);
            $returnObj->cover = $this->getCoverUrl($material);
            $returnObj->details = $this->processExemplaries($exemplaries);
            $returnObj->materialType = $material->materialTypeDescription;
            $returnObj->hasReservable = $this->hasReservableExemplaries($controlNumber, $libraryUnitId);

            $returnObj->isCollection = $busMaterialControl->isCollection($controlNumber);
            $returnObj->isFascicle = $busMaterialControl->isCollectionFascicle($controlNumber);
            $retorno->search[] = $returnObj;
        }

        if (!isset($retorno->search) || empty($retorno->search)) 
        {
            $retorno->notFoundMessage = 'não gerou nenhum resultado';
        }

        $retorno->count = $busGenericSearch->getCount();
        $retorno->recordsPerPage = LISTING_NREGS;
        return json_encode($retorno);
    }

    /**
     * Processa os exemplares e retorna um array formatado com os detalhes
     */
    private function processExemplaries($exemplaries)
    {
        if ( count($exemplaries) > 0 )
        {
            foreach ( $exemplaries as $exemplary )
            {
                // Se ele é emprestável.
                if ( $exemplary->exemplaryStatus->executeLoan == DB_TRUE )
                {
                    $vol = isset($exemplary->volume) ? 'vol.' . $exemplary->volume : 'vol. 1';
                    $key = $exemplary->materialTypeDescription . '(s) ' . $vol . ' para retirada em ' . $exemplary->libraryName;
                }
                else
                {
                    $key = false;
                }
                $exemplariesArray[$key] = isset($exemplariesArray[$key]) ? $exemplariesArray[$key] + 1 : 1;
            }

            foreach ($exemplariesArray as $detail => $amount)
            {
                if (!$detail) 
                {
                    $detail = $amount == 1 ? 'exemplar indisponível para retirada' : 'exemplares indisponíveis para retirada';
                }
                $details[] = $amount . ' ' . $detail;
            }
        }
        return $details ?? ['Nenhum exemplar disponível no momento'];
    }

    /**
     * Obtém a imagem da capa do exemplar, caso não possua, aplica um URL padrão
     */
    private function getCoverUrl($material)
    {
        $busFile = $this->MIOLO->getBusiness('gnuteca3', 'BusFile');
        $controlNumberFather = $material->controlNumberFather;
        $baseUrl = $this->MIOLO->getAbsoluteURL(null) . 'miolo25/html/file.php?folder=cover&file=';

        $fileDataObject = (object) [
            "folder" => "cover",
            "fileName" => ($controlNumberFather ?? $material->controlNumber) . '.',
        ];
        $busFile->setData($fileDataObject);
        $image = $busFile->searchFile(true)[0];

        if (
            $busFile->fileExists('cover', $material->controlNumber . '.')
            || ($controlNumberFather != null && $busFile->fileExists('cover', $controlNumberFather . '.'))
        ) {
            // $baseUrl . $material->controlNumber . ''
            return $baseUrl . $image->basename;
        }

        if (COVER_IMAGE_NOT_AVAIABLE)
        {
            return $baseUrl . COVER_IMAGE_NOT_AVAIABLE;
        }

        // Se não existir nenhuma imagem de capa, retorna null
        return null;
    }

    /**
     * Define a ordenação dos resultados
     */
    private function setOrderResult($busGenericSearch, $orderField = null, $orderType = null)
    {
        // Define a ordenação dos resultados.
        if (strlen(SIMPLE_SEARCH_DEFAULT_ORDER) > 0) 
        {
            list($field, $type) = explode(',', SIMPLE_SEARCH_DEFAULT_ORDER);

            //Defaults
            if (!$field) {
                $field = 1;
            }

            if (!$type) {
                $type = 'ASC';
            }

            $types = array(
                'ASC' => SORT_ASC,
                'DESC' => SORT_DESC
            );

            $orderField = $field;
            $orderType = $types[$type];
        }

        if ($orderField && $orderType) 
        {
            $busSearchableField = $this->MIOLO->getBusiness('gnuteca3', 'BusSearchableField');
            $orderFields = $busSearchableField->getDetaisForOrder($orderField);
            $orderField = explode(',', $orderFields->field); // separa por virgula, caso tenha vários campos

            foreach ($orderField as $f) 
            {
                $fieldsX = explode("+", $f);

                foreach ($fieldsX as $f) 
                {
                    list($fi, $su) = explode('.', $f); // separa field e subfield
                    $fieldType = is_null($orderFields->fieldType) ? $orderFields->fieldType : SORT_STRING;
                    $busGenericSearch->setOrder($fi, $su, $orderType, $fieldType);
                }
            }
        }
    }

    /**
     * Pesquisa se o material possui algum exemplar reservável
     */
    private function hasReservableExemplaries($controlNumber, $libraryUnitId) 
    {
        $this->MIOLO->uses('classes/controls/GMaterialDetail.class.php', 'gnuteca3');
        $busExemplaryControl = $this->MIOLO->getBusiness('gnuteca3', 'BusExemplaryControl');
        
        $grouped = [];
        // Obtém os exemplares e os seus estados
        $exemplaries = $busExemplaryControl->getExemplaryOfMaterial($controlNumber, $libraryUnitId, true, true, true);
        foreach ($exemplaries as $exemplar) 
        {
            if (
                $exemplar->exemplaryStatus->executeReserve === 't' &&
                $exemplar->exemplaryStatus->meetReserve === 't'
            ) {
                $libraryUnitId = $exemplar->libraryUnitId;
                $tomo = $exemplar->tomo ?? '-';
                $volume = $exemplar->volume ?? '-';
                
                // Cria uma chave única para o agrupamento
                $groupKey = $libraryUnitId . '|' . $tomo . '|' . $volume;
                $grouped[$groupKey]['itemNumbers'][] = $exemplar->itemNumber;
            }
        }
        
        if (count($grouped) === 1) 
        {
            $grouped[$groupKey]['libraryUnitId'] = $libraryUnitId;
            return $grouped[$groupKey];
        }
        
        if (empty($grouped)) 
        {
            return false;
        }
        
        return true;
    }
}