<?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
     */
    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);

            // Exemplares
            $exemplaries = $busExemplaryControl->getExemplaryOfMaterial($controlNumber, null, true);


            // Solução temporária para separar as características de cada material no searchformat
            //////////////////////////////////////////////////////////////////////
            $returnObj = new stdClass();
            $searchformat = $busSearchFormat->formatSearchData(1, $line, null, $material->category);
            $returnObj->controlNumber = $controlNumber;

            // Expressão regular para encontrar o tipo
            preg_match('/<font[^>]*>(.*?)<\/font>/', $searchformat, $matches);
            if (isset($matches[1])) {
                $returnObj->searchFormat->type = trim($matches[1]); // Captura o tipo (Livro)
            }

            // Expressão regular para encontrar o título
            preg_match('/<b>\s*Título:\s*<\/b>\s*(.*?)(?=<br\/>)/', $searchformat, $matches);
            if (isset($matches[1])) {
                $returnObj->searchFormat->title = trim($matches[1]);
            }

            // Expressão regular para encontrar o autor
            preg_match('/<b>\s*Autor:\s*<\/b>\s*(.*?)(?=<br\/>)/', $searchformat, $matches);
            if (isset($matches[1])) {
                $returnObj->searchFormat->author = trim($matches[1]);
            }

            // Expressão regular para encontrar a classificação
            preg_match('/<b>Classificação:\s*<font[^>]*>\s*(.*?)\s*<\/font><\/b>/', $searchformat, $matches);
            if (isset($matches[1])) {
                $returnObj->searchFormat->classification = trim($matches[1]);
            }
            ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

            // Cria o objeto
            // $returnObj = new stdClass();
            // $returnObj->searchFormat = $busSearchFormat->formatSearchData(1, $line, null, $material->category);
            $returnObj->cover = $this->getCoverUrl($material);
            $returnObj->details = $this->processExemplaries($exemplaries);
            $returnObj->hasFascicles = $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->records_per_page = 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 = 'exemplares indisponíveis para retirada';
                }
                $exemplariesArray[$key] = isset($exemplariesArray[$key]) ? $exemplariesArray[$key] + 1 : 1;
            }

            foreach ($exemplariesArray as $detail => $amount)
            {
                $details[] = $amount . ' ' . $detail;
            }
        }
        return $details ?? 'Nenhum exemplar localizado.';
    }

    /**
     * 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=';
        // $baseUrl = 'http://trunk.instituicao.com.br/miolo25/html/file.php?folder=cover&file=';
        if ($busFile->fileExists('cover', $material->controlNumber . '.'))
        {
            return $baseUrl . $material->controlNumber . '.png';
        }

        if ($controlNumberFather && $coverFatherExists = $busFile->fileExists('cover', $controlNumberFather . '.'))
        {
            return $baseUrl . $controlNumberFather . '.png';
        }

        if (COVER_IMAGE_NOT_AVAIABLE)
        {
            return $baseUrl . COVER_IMAGE_NOT_AVAIABLE;
        }
        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);
                }
            }
        }
    }
}
