<?php

use DocuSign\eSign\Api\TemplatesApi;
use DocuSign\eSign\Client\ApiClient;
use DocuSign\eSign\Model\Tabs;
use DocuSign\eSign\Model\EnvelopeTemplate;

class Agro_DocuSign_Template
{
    protected string $id;
    protected TemplatesApi $templateApi;
    protected Tabs $tabs;
    protected EnvelopeTemplate $envelopeTemplate;
    protected $idGroupTabs = [];
    protected $parametros = null;
    protected string $mensagemErros = "";

    /**
     *  @param string[] $camposText
     */
    protected array $camposText = [];
    /**
     *  @param boolean[] $camposRadioGroup
     */
    protected array $camposRadioGroup = [];
    /**
     *  @param boolean[] $camposCheckbox
     */
    protected array $camposCheckbox = [];

    /**
     * __construct
     *
     * @param  ApiClient $apiClient
     */
    public function __construct(ApiClient $apiClient, ?array $parametros = null)
    {
        $this->templateApi = new TemplatesApi($apiClient);
        $this->parametros = $parametros;

        $this->preencherCampos();
    }

    /**
     * Retorna as tabs (campos adicionados no template) de um documento
     *
     * @param  string $documentoId
     * @return Tabs
     */
    public function getTabsByDocument(string $documentoId = '1')
    {
        if (empty($this->tabs)) {
            $this->tabs = $this->templateApi->getDocumentTabs(Agro_DocuSign_Auth::$docusignApiAccountId, (string) $documentoId, $this->id);
        }

        return $this->tabs;
    }

    public function setTabs($tabs)
    {
        $this->tabs = $tabs;
    }

    /**
     * Adiciona um valor a um campo do layout
     *
     * @param  string $chave Nome do label no documento do template no DocuSign
     * @param  string $valor Valor que seja adicionar no campo
     */
    public function addCampoText(string $chave, string $valor)
    {
        $this->camposText[$chave] = $valor;
    }
 
    /**
     * Percorre os campos textos dinâmicos do template,
     * valida se existe o label do campo no array $campoText
     * e adiciona o valor no campo do template
     */
    private function deParaCamposText(string $idDocument)
    {

        foreach ($this->getTabsByDocument()->getPrefillTabs()->getTextTabs() as &$textTabs) {

            $label = $textTabs->getTabLabel();
            if (array_key_exists($textTabs->getTabLabel(), $this->camposText)) {
                $textTabs->setDocumentId($idDocument);
                $textTabs->setValue($this->camposText[$label]);
            }
        }
    }

    /**
     * Percorre os campos checkbox dinâmicos do template,
     * valida se existe o label do campo no array $camposCheckbox
     * e adiciona o valor no campo do template
     */
    private function deParaCamposCheckbox(string $idDocument)
    {
        foreach ($this->getTabsByDocument()->getPrefillTabs()->getCheckboxTabs() as &$checkboxTab) {

            $label = $checkboxTab->getTabLabel();
            if (array_key_exists($checkboxTab->getTabLabel(), $this->camposCheckbox)) {
                $checkboxTab->setDocumentId($idDocument);
                $checkboxTab->setSelected($this->camposCheckbox[$label]);
            }
        }
    }

     
    /**
     * Percorre os campos radio dinâmicos do template,
     * valida se existe o label do campo no array $camposRadioGroup
     * e adiciona o valor no campo do template
     */
    private function deParaCamposRadio(string $idDocument)
    {
        $radiosGroup = null;
        foreach ($this->getTabsByDocument()->getPrefillTabs()->getRadioGroupTabs() as &$radioGroup) {
            $groupName = $radioGroup->getGroupName();
            if (array_key_exists($groupName, $this->camposRadioGroup)) {
                foreach ($radioGroup->getRadios() as $radios) {
                    $radios->setSelected(false);
                    if ($radios->getValue() == $this->camposRadioGroup[$groupName]) {
                        $radios->setSelected(true);
                    }
                }

                $radiosGroup[] = $radioGroup;
            }
        }

        $this->tabs->getPrefillTabs()->setRadioGroupTabs($radiosGroup);
    }

    protected function preencherCampos() {}

    /**
     * Percorre todos os deparas e retorna as tabs com os valores atualizados
     * @return Tabs
     */
    public function deParaCampos(string $idDocument = '1'): Tabs
    {
        $this->getTabsByDocument();

        if (!empty($this->getTabsByDocument()->getPrefillTabs())) {
            if (!empty($this->camposText)) {
                $this->deParaCamposText($idDocument);
            }
    
            if (!empty($this->camposCheckbox)) {
                $this->deParaCamposCheckbox($idDocument);
            }
    
            if (!empty($this->camposRadioGroup)) {
                $this->deParaCamposRadio($idDocument);
            } else {
                $this->tabs->getPrefillTabs()->setRadioGroupTabs(null);
            }
        }

        $tabs = new Tabs();
        $tabs->setPrefillTabs($this->tabs->getPrefillTabs());

        return $tabs;
    }
    
    /**
     * Retorna o id do template
     *
     * @return string
     */
    public function getId(): string
    {
        return $this->id;
    }

    /**
     * Retorna a instância da api de template
     *
     * @return TemplatesApi
     */
    public function getTemplateApi(): TemplatesApi
    {
        return $this->templateApi;
    }

    /**
     * Retorna o envelopeTemplate pelo id do template.
     * envelopeTemplate são as definições salvas no site para ele como recipients, roles, documents
     *
     * @return EnvelopeTemplate
     */
    public function getEnvelopeTemplate(): EnvelopeTemplate
    {
        if (empty($this->envelopeTemplate) && !empty($this->id)) {
            $this->envelopeTemplate = $this->templateApi->get(Agro_DocuSign_Auth::$docusignApiAccountId, $this->id);
        }
        
        return $this->envelopeTemplate;
    }

    /**
     * Retorna a mensagem de erro, caso houver, no preenchimento dos campos preFillFields no método preencherCampos
     * 
     * @return string
     */
    public function getMensagemErros(): string
    {
        return $this->mensagemErros;
    }

    /**
     * Divide uma string com limite de tamanho informado e retorna um array
     * 
     * @param string $texto
     * @param int $limite
     */
    protected function quebrarString(string $texto, int $limite = 70): array
    {
        $texto = wordwrap($texto, $limite, "|");
        return explode("|", $texto);
    }
}