<?php

namespace Teknisa\Libs\Util;

use Teknisa\Libs\Exception\CustomException;
use Zeedhi\Framework\DependencyInjection\InstanceManager;
use Teknisa\Libs\Util\Environment;
use Zeedhi\Framework\DataSource\Manager\SQL\ManagerImpl;
use Zeedhi\Framework\DataSource\FilterCriteria;
use Zeedhi\Framework\DTO;
use Zeedhi\Framework\DataSource\DataSet;
use Zeedhi\Framework\ORM\DateTime;
use Zeedhi\Framework\Util\Crypt;
use Doctrine\ORM\EntityManager;
use Zeedhi\Framework\DTO\Response\Error;
use Zeedhi\Framework\DTO\Request;
use Zeedhi\Framework\DTO\Response;

class Utilities {

    const NRORG_FILTER_ZHU_LOG = " AND ORGANIZATION_ID = ";

    const PARAMGERAL  = 'paramgeral';
    const PARAMFILIAL = 'paramfilial';

    const PRODUCT_MENU_NAME = 'product';
    const JSON_EXTENSION = 'json';
    const GENERATED_FILE_NAME = 'modulesVersion';

    const LOGIN_CRYPT_STRING = '1460_loginManagement';

    protected $environment;
    protected $dataSourceManager;
    protected $zhCrypt;
    const DATE_TIME_ZONE_SP = 'America/Sao_Paulo';

    const FORMAT_DATE_DEFAULT = 'd/m/Y H:i:s';

    public static function getCurrentDateTimeString() {
        $currentDate = new \DateTime();
        return $currentDate->format(self::FORMAT_DATE_DEFAULT);
    }

    public function __construct(Environment $environment, ManagerImpl $dataSourceManager, Crypt $zhCrypt) {
        $this->environment = $environment;
        $this->dataSourceManager = $dataSourceManager;
    }

    /**
     * @param $token
     * @param $requestType
     * @param $data
     * @param $dataSetResultPos
     * @param $privateKey
     * @param $url
     * @param bool $keepConnected
     * @return array
     * @throws \Exception
     */
    public static function callWebService($token, $requestType, $data, $dataSetResultPos, $privateKey, $url, $keepConnected = false){
        set_time_limit(180);
        $header = array();
        $header[] = 'OAuth-Token: ' . $token;
        $header[] = 'OAuth-SecretId: ' . $privateKey;
        if($keepConnected) {
            $header[] = 'OAuth-KeepConnected: ' . $keepConnected;
        }
        $header[] = 'Content-Type: application/json';
        $header[] = 'Content-Length: ' . strlen(json_encode($data));

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
        curl_setopt($ch, CURLOPT_URL, $url . $requestType);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
        curl_setopt($ch, CURLOPT_TIMEOUT, 300);

        $result = curl_exec($ch);
        $result = json_decode($result, true);
        $error = curl_error($ch);
        curl_close($ch);

        if (!empty($result['error'])) {
            throw new \Exception($result['error'], 500);
        } else if (!empty($error)) {
            throw new \Exception($error, 500);
        } else {
            return isset($result['dataset'][$dataSetResultPos]) ? $result['dataset'][$dataSetResultPos] : null;
        }
    }

    /**
     * @param array[] $filters
     * @param $nameFilter
     * @param bool $remove
     * @return null
     */
    public static function getValueInFilterDataSourceByName(array &$filters,$nameFilter,$remove = false)
    {
        foreach ($filters as $key => $filter) {
            $name = $filter['columnName'];
            $values = $filter['value'];
            if($name == $nameFilter ){
                if($remove){
                    unset($filters[$key]);
                }
                return $values;
            }
        }
        return null;
    }

    /**
     * @param $string
     * @return string
     */
    public static function encrypt($string){
        return md5($string);
    }

    public static function getDelphiPasswordEncrypted($password, $isEncrypt = true) {
        if($isEncrypt) {
            return DelphiCrypt::encrypt($password);
        }
        return DelphiCrypt::decrypt($password);
    }

    /**
     * @param $password
     * @param bool $isEncrypt
     * @return mixed
     * @throws \Exception
     */
    public static function getDelphiPasswordEncryptedLegacy($password, $isEncrypt = true) {
        $url = self::getAspUrlParameter() . '/comwebservice/service.asmx?wsdl';

        $options = array(
            'encoding'    => 'ISO-8859-1',
            'trace'       => true,
            'exceptions'  => true,
            'compression' => SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP,
        );

        $args = array(
            new \SoapVar($password, XSD_STRING, 'string', "http://www.w3.org/2001/XMLSchema")
        );

        $cryptType = $isEncrypt ? 'GetCriptoPass' : 'GetUnCriptoPass';
        $params = array(
            'rdm'    => 'Bib_html.rdmDBGeralHtm',
            'method' => $cryptType,
            'args'   => $args,
        );

        try {
            $client = new \SoapClient($url, $options);
            $result = $client->executeCOMMethod($params);
            $encryption = $result->executeCOMMethodResult;
        } catch (\SoapFault $e) {
            throw new \Exception($e->getMessage());
        }

        return $encryption;
    }

    public static function getCurrentIp() {
        if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
            return $_SERVER['HTTP_CLIENT_IP'];
        }
        if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            return $_SERVER['HTTP_X_FORWARDED_FOR'];
        }

        return $_SERVER['REMOTE_ADDR'];
    }

    public static function createQueryFiltered($filters, $tableAlias = null, $useZhuLogFilters = false)
    {
        $filterSQL = '';
        foreach ($filters as $filter) {
            $name = $filter['columnName'];
            $operator = $filter['operator'] == "LIKE_I" ? "LIKE" : $filter['operator'];
            $values = $filter['value'];
            if (($name != '*' && !empty($values)) || $values == 0) {
                if ($operator == 'BETWEEN') {
                    if ($values[0] && $values[1]) {
                        $values = "TO_DATE( '$values[0] 00:00:00' ,'DD/MM/YYYY HH24:MI:SS')
                                AND TO_DATE( '$values[1] 23:59:59' ,'DD/MM/YYYY HH24:MI:SS')";
                    } else if ($values[0]) {
                        $operator = '>';
                        $values = "TO_DATE( '$values[0] 00:00:00' ,'DD/MM/YYYY HH24:MI:SS')";
                    } else if ($values[1]) {
                        $operator = '<';
                        $values = "TO_DATE( '$values[1] 00:00:00' ,'DD/MM/YYYY HH24:MI:SS')";
                    } else {
                        $values = "";
                    }

                    if ($values || ($values && ($values[0] || $values[1]))) {
                        if (!empty($tableAlias)) {
                            $filterSQL .= "AND $tableAlias.$name $operator $values";
                        } else {
                            $filterSQL .= "AND $name $operator $values";
                        }
                    }
                } else {
                    if (is_array($values) && $operator != 'MAPPED_LIKE_ALL') {
                        $stringValues = "('" . implode("','", $values) . "')";
                        $values = $stringValues;
                    }
                    if ($operator == 'LIKE') {
                        if (!empty($tableAlias)) {
                            $values = "UPPER('" . $values . "')";
                            $name = "UPPER($tableAlias.$name)";
                        } else {
                            $values = "UPPER('" . $values . "')";
                            $name = "UPPER($name)";
                        }
                    }
                    if ($operator == 'LIKE_ALL') {
                        if (!empty($tableAlias)) {
                            $values = "UPPER('" . $values . "')";
                        } else {
                            $values = "UPPER('" . $values . "')";
                        }

                        $columnList = explode('|', $name);
                        $likes = array();
                        foreach ($columnList as $column) {
                            $likes[] = "UPPER($column) LIKE $values";
                        }
                        $filterLikeAll = implode(' OR ', $likes);
                        $filterSQL .= "AND ( $filterLikeAll )";

                    } else if ($operator == 'LIKE') {
                        $filterSQL .= "AND $name $operator $values";
                    } else if ($operator == 'MAPPED_LIKE_ALL') {
                        $customZhuLogFilters = array ();
                        foreach($values[0] as $index => $mappedLikeAllValues) {
                            if($index == '_ALL') {
                                $columnList = explode('|', explode('#', $name)[0]);
                                $likes = array();
                                foreach ($columnList as $column) {
                                    if($useZhuLogFilters && $column == 'ROUTE_LABEL') {
                                        $column = 'ROUTE';
                                    }
                                    if($useZhuLogFilters && isset($customZhuLogFilters[$column])) {
                                        $likes[] = $customZhuLogFilters[$column] . $mappedLikeAllValues . "')";
                                    } else {
                                        $likes[] = "UPPER($column) LIKE UPPER('" . $mappedLikeAllValues . "')";
                                    }
                                }
                                $filterLikeAll = implode(' OR ', $likes);
                                $filterSQL .= " AND ( $filterLikeAll )";
                            } else {
                                if($useZhuLogFilters && $index == 'ROUTE_LABEL') {
                                    $index = 'ROUTE';
                                }
                                $stringValues = "('" . implode("','", $mappedLikeAllValues) . "')";
                                if (!empty($tableAlias)) {
                                    $filterSQL .= " AND $tableAlias.$index IN $stringValues ";
                                } else {
                                    $filterSQL .= " AND $index IN $stringValues ";
                                }
                            }
                        }
                    } else {
                        if (!empty($tableAlias)) {
                            $filterSQL .= "AND $tableAlias.$name $operator $values";
                        } else {
                            $filterSQL .= "AND $name $operator $values";
                        }
                    }
                }
            }
        }
        return $filterSQL;
    }

    /**
     * @return EntityManager
     */
    public static function getEntityManager(){
        return InstanceManager::getInstance()->getService('entityManager');
    }

    public static function zeedhiEncrypt($text, $key = 'libraries') {
        return Crypt::encrypt($text, $key );
    }

    public static function zeedhiDecrypt($text, $key = 'libraries') {
        return Crypt::decrypt($text, $key );
    }

    public static function legacyEncrypt($text, $salt = 'libraries', $padWith = '\0') {
        $encryptedString = trim(
            base64_encode(
                mcrypt_encrypt(
                    MCRYPT_RIJNDAEL_256,
                    str_pad($salt, 32, $padWith),
                    $text,
                    MCRYPT_MODE_ECB,
                    mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND)
                )
            )
        );
        return $encryptedString;
    }

    public static function legacyDecrypt($text, $salt = 'libraries',  $padWith = '\0') {
        $decryptedString = trim(
            mcrypt_decrypt(
                MCRYPT_RIJNDAEL_256,
                str_pad($salt, 32, $padWith),
                base64_decode($text),
                MCRYPT_MODE_ECB,
                mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND)
            )
        );
        return $decryptedString;
    }

    /* TEKNISA FUNCTIONS -------------------------------------------------------------------------------------------- */
    public function retornaDataProcessamento() {
        $dataSet = $this->dataSourceManager->findBy(new FilterCriteria(self::PARAMGERAL),
            array('NRORG' => $this->environment->getNrOrg()));
        $rows = $dataSet->getRows();
        if ($rows[0]['IDUTILDTPROC'] != 'S') {
            $dataProcessamento = date('d/m/Y');
        } else {
            $dataProcessamento = $this->retornaDataProcPorFilial($this->environment->getCdFilial());
        }

        return $this->truncDate($dataProcessamento);
    }



    public function retornaDataProcPorFilial($cdfilial) {
        $filterCriteria = new FilterCriteria(self::PARAMFILIAL);
        $filterCriteria->addCondition('CDFILIAL', $cdfilial);
        $filterCriteria->addCondition('NRORG', $this->environment->getNrOrg());
        $dataSet = $this->dataSourceManager->findBy($filterCriteria);
        $rows = $dataSet->getRows();
        if (!empty($rows) && !empty($rows[0]) && $rows[0]['DTPROCESSA']) {
            $dataProcessamento = $rows[0]['DTPROCESSA'];
        }
        else{
            $dataProcessamento = date('d/m/Y');
        }

        return $this->truncDate($dataProcessamento);

    }

    private function truncDate($date) {
        $date = explode(' ', $date);
        return $date[0];
    }

    public function validateUserGroup(DTO\Request\Row $request, DTO\Response $response) {
        $row = $request->getRow();
        $permission = array('isValid' => $this->permissaoOperadorPorGrupo($row));
        $response->addDataSet(new DataSet('permission', $permission));
    }

    public function permissaoOperadorPorGrupo($row) {
        $filterCriteria = new FilterCriteria('opergrupop');
        $filterCriteria->addCondition('CDOPERADOR', $row['cdoperador']);
        $filterCriteria->addCondition('CDGRUPOPER', $this->retornaGrupoDeOperador($row['idgrupoper']));
        $filterCriteria->addCondition('NRORG', $this->environment->getNrOrg());

        $dataSet = $this->dataSourceManager->findBy($filterCriteria);
        $rows = $dataSet->getRows();

        return isset($rows[0]) ? true : false;
    }

    public function retornaGrupoDeOperador($idautgrupop) {
        $filterCriteria = new FilterCriteria('autgrupop');
        $filterCriteria->addCondition('IDAUTGRUPOP', $idautgrupop);
        $filterCriteria->addCondition('NRORG', $this->environment->getNrOrg());

        $dataSet = $this->dataSourceManager->findBy($filterCriteria);
        $rows = $dataSet->getRows();

        return isset($rows[0]) ? $rows[0]['CDGRUPOPER'] : null;

    }

    public function retornaCentralDefault() {
        $filterCriteria = new FilterCriteria('filial');
        $filterCriteria->addCondition('CDFILIAL', $this->environment->getCdFilial());
        $filterCriteria->addCondition('NRORG', $this->environment->getNrOrg());

        $dataSetLogged = $this->dataSourceManager->findBy($filterCriteria);
        $rowsLogged = $dataSetLogged->getRows();
        if($rowsLogged[0]['CDFILCENTPME']) {
            $filterCriteria = new FilterCriteria('filial');
            $filterCriteria->addCondition('CDFILIAL', $rowsLogged[0]['CDFILCENTPME']);
            $filterCriteria->addCondition('NRORG', $this->environment->getNrOrg());

            $dataSet = $this->dataSourceManager->findBy($filterCriteria);
            $rows = $dataSet->getRows()[0];
        } else {
            $filterCriteria = new FilterCriteria('filial');
            $filterCriteria->addCondition('CDFILCENTPME', $this->environment->getCdFilial());
            $filterCriteria->addCondition('NRORG', $this->environment->getNrOrg());

            $dataSet = $this->dataSourceManager->findBy($filterCriteria);
            $rows = $dataSet->getRows();
            if(count($rows) > 0) {
                $rows = $rowsLogged[0];
            }
        }

        return $rows;

    }

    /**
     * Converte um string decimal em Float
     * @param $string
     * @return float
     */
    public static function decimalToFloat($string)
    {
        return (float)str_replace(',', '.', $string);
    }

    /**
     * Converte uma string na codificacao iso-8859-1 para utf-8
     * @param $str
     * @return string
     */
    public static function convertISOToUTF8($str)
    {
        $encoding = mb_detect_encoding($str, 'utf-8, iso-8859-1, ascii', true);
        if (strcasecmp($encoding, 'UTF-8') !== 0) {
            $str = iconv($encoding, 'utf-8', $str);
        }

        return $str;
    }

    /**
     * Retira os acentos de uma string.
     *
     * @param string $text string com acentos.
     *
     * @return string
     */
    public static function removeAccents($text) {
        return strtr(utf8_decode($text), utf8_decode("áàãâéêíóôõúüçñÁÀÃÂÉÊÍÓÔÕÚÜÇÑ"), "aaaaeeiooouucnAAAAEEIOOOUUCN");
    }

    /* Cria um arquivo zip com os arquivos passados como parametro
     *
     * @param string $filesUrl Array dos arquivos a serem zipados (caminho completo de cada arquivo)
     * @param string $zipName Nome do arquivo zip a ser criado (caminho completo)
     *
     * @return string caminho completo do zip
     */
    public function zipFiles($filesUrl, $zipname){
        $zip = new \ZipArchive;

        if(is_file($zipname))
            $zip->open($zipname, \ZipArchive::OVERWRITE);
        else
            $zip->open($zipname, \ZipArchive::CREATE);
        foreach ($filesUrl as $file) {
            $filename = explode(DIRECTORY_SEPARATOR, $file);
            $zip->addFile($file, end($filename));
        }

        $caminhoZip = $zip->filename;
        $zip->close();

        return $caminhoZip;
    }

    public static function getProductBasePath($isModulePath = false) {
        if(strpos(__DIR__, 'modules') === false || $isModulePath) {
            return explode('backend', __DIR__)[0];
        }
        return explode('modules', __DIR__)[0];
    }

    public static function downloadAndRemoveFile($fileDir, $fileName) {
        header('Accept-Ranges: none');
        header("Content-Type: text/plain");
        header("Content-Length: " . filesize($fileDir));
        header("Content-Disposition: attachment; filename=" . $fileName);

        readfile($fileDir);
        unlink($fileDir);
        exit;
    }

    public static function getGeneratedFile($ext = self::JSON_EXTENSION, $fileName = self::GENERATED_FILE_NAME) {
        return self::getGeneratedFileDir() . $fileName . '_' . rand(0, 999999) . '.' . $ext;
    }

    public static function getGeneratedFileDir() {
        return __DIR__ . '/../../../../config/';
    }

    public static function getLoginConfig() {
        return json_decode(file_get_contents(__DIR__ . '/../../../../config/config.json'), true);
    }

    public static function getLoginIntegration() {
        return json_decode(file_get_contents(__DIR__ . '/../../../../config/integration.json'), true)[0];
    }

    public static function getArrayFromAssociativeArray( array $array = array(), $key = 'ID')
    {
        $result = array();
        foreach ($array as $row) {
            $result[] = $row[$key] ;
        }
        return $result;
    }

    public static function getTokenLifeTimeParameter() {
        return InstanceManager::getInstance()->getParameter('tokenLifeTime');
    }

    public static function getAspUrlParameter() {
        return InstanceManager::getInstance()->getParameter('aspUrl');
    }

    public static function getProjectIdParameter() {
        return InstanceManager::getInstance()->getParameter('projectId');
    }

    public static function useRateLimit() {
        try {
            return intval(InstanceManager::getInstance()->getParameter('useRateLimit'));
        } catch(\Exception $e) {
            return true;
        }
    }

    public static function getSecRateLimit() {
        try {
            return intval(InstanceManager::getInstance()->getParameter('secRateLimit'));
        } catch(\Exception $e) {
            return 10;
        }
    }

    public static function getQuantLimit() {
        try {
            return intval(InstanceManager::getInstance()->getParameter('quantRateLimit'));
        } catch(\Exception $e) {
            return 30;
        }
    }

    public static function getUseSQLWebTunningParameter() {
        try {
            return InstanceManager::getInstance()->getParameter('useSQLWebTunning') == 'true';
        } catch(\Exception $e) {
            return true;
        }
    }

    public static function getConcurrentAccessSaveInMongoParameter() {
        try {
            return InstanceManager::getInstance()->getParameter('concurrentAccessSaveInMongo') == 'true';
        } catch(\Exception $e) {
            return false;
        }
    }

    public static function getShowDbInVersionInfoParameter() {
        try {
            return InstanceManager::getInstance()->getParameter('showDbInVersionInfo') == 'true';
        } catch(\Exception $e) {
            return true;
        }
    }

    public static function getModulesNotRedirectParameter() {
        try {
            return InstanceManager::getInstance()->getParameter('modulesNotRedirect');
        } catch(\Exception $e) {
            return array();
        }
    }

    public static function getPHPErrorLogPath() {
        try {
            return InstanceManager::getInstance()->getParameter('PHPErrorLogPath');
        } catch(\Exception $e) {
            return '/var/www/logs/apache-logs';
        }
    }

    /**
     * @param CustomException $e
     * @return Error
     */
    public static function getErrorObjectFromException(CustomException $e) {
        $error = array (
            'CODE'   => $e->getMessage(),
            'PARAMS' => $e->getParams()
        );
        return new Error(json_encode($error), $e->getCode());
    }

    /**
     * @param $collectionIds  => ID ou ARRAY da(s) coleta(s) (Cod Filial, Cod Operador, Cod da Loja, ...)
     * @param $operationId    => ID da operação (Retirada, Cardápio, Login, ...)
     * @param $productId      => Código do Produto (opcional).
     * @param $operatorCode   => Código do Operador (opcional).
     * @param $operatorName   => Nome do Operador (opcional).
     * @param $organizationId => Código do organização (opcional).
     */
    public static function saveCollectedData($collectionIds, $operationId, $productId = null, $operatorCode = null, $operatorName = null, $organizationId = null) {
        $collectionIds = is_array($collectionIds) ? $collectionIds : array($collectionIds);
        foreach($collectionIds as $collectionId) {
            try {
                $logType        = '1';
                $productId      = $productId      ?: self::getProjectIdParameter();
                $organizationId = $organizationId ?: InstanceProvider::getEnvironment()->getCurrentOrganizationId();
                $operatorCode   = $operatorCode   ?: InstanceProvider::getEnvironment()->getCurrentUserId();
                $collectedDataRepository = InstanceProvider::getLibCollectedDataRepository();
                $newEntityManager        = InstanceProvider::getConnectionCustom()->updateVpdConnection($organizationId);
                if($newEntityManager) {
                    $collectedDataRepository->setEntityManager($newEntityManager);
                }
                $collectedData = $collectedDataRepository->findCollectedData($productId, $collectionId, $organizationId);
                
                if(empty($collectedData)) {
                    $collectedDataRepository->insertCollectedData($productId, $collectionId, $operationId, $organizationId, $operatorCode);
                } else {
                    $logType = '2';
                    $collectedDataRepository->updateCollectedData($productId, $collectionId, $operationId, $organizationId, $operatorCode);
                }
            } catch(\Exception $e) {
                try {
                    $operatorName = $operatorName ?: InstanceProvider::getEnvironment()->getCurrentUserName();
                    $observation  = "Tentativa de gravação com os dados NRPRODUTO: $productId, IDCOLETA: $collectionId, IDOPERACAO: $operationId e NRORG: $organizationId retornou o erro: ". $e->getMessage();
                    $searchItem   = "NRPRODUTO=$productId IDCOLETA=$collectionId NRORG=$organizationId";
                    $host         = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : $_SERVER['SERVER_NAME'];
                    $connParams   = InstanceProvider::getEntityManager()->getConnection()->getParams();
                    $dbUserName   = isset($connParams['sessionMode']) ? $connParams['dbname'] : $connParams['user'];
                    $collectedDataRepository->insertLogOpera($logType, $observation, $searchItem, gethostbyname($host), $dbUserName, $organizationId, $operatorCode, $operatorName, $productId);
                } catch(\Exception $e) { }
            }
        }
    }

    public static function getOrganizationAndBranchesIds($organizationId = null)
    {
        $nrorg = InstanceProvider::getSession()->get('NRORGOPER') ?: InstanceProvider::getEnvironment()->getCurrentOrganizationId();
        $organizationId = $organizationId ?: $nrorg;
        $oAccTekMgrRepository = InstanceProvider::getLibOAccTekMgrRepository();
        $oAccTekMgr = $oAccTekMgrRepository->getOAccTekMgr($organizationId);
        $data = json_decode(self::zeedhiDecrypt($oAccTekMgr[0]['OACCTEK_PHP7'], self::LOGIN_CRYPT_STRING), true);
        return isset($data['organizationAndBranchesIds']) ? $data['organizationAndBranchesIds'] : array();
    }
    
    public static function getValidOrganizationAndBranches(Request $request, Response $response)
    {
        $arrBranches = Utilities::getOrganizationAndBranchesIds();
        $response->addDataSet(new DataSet('validBranches', $arrBranches));
    }
    
    public function saveOrgFilial(Request\DataSet $request, Response $response)
    {
        try {
            $row            = $request->getDataSet()->getRows()[0];
            $organizationId = $this->environment->getNrOrg();
            $cdfilial       = $row['CDFILIAL'];
            self::callLicenseSaveOrgFilial($organizationId, $cdfilial);
        } catch(\Exception $e) {
            $response->setError(new Response\Error($e->getMessage(), Response\Message::TYPE_ERROR));
        }
    }
    
    public static function callLicenseSaveOrgFilial($organizationId, $cdfilial) {
        $nrorg = self::readOAccCustom();
        $organizationId = $nrorg ? $nrorg : $organizationId;
        $filiais = is_array($cdfilial) ? $cdfilial : array($cdfilial);
        $productPath = self::getProductBasePath();
        $loginConfig = json_decode(file_get_contents($productPath . '/modules/login/backend/vendor/teknisa/libraries/config/config.json'), true);
        
        foreach($filiais as $cdfilial) {
            $params = array(
                "requestType" => "DataSet",
                "dataset"     => array(array(
                    'NRORG'    => $organizationId,
                    'CDFILIAL' => $cdfilial
                ))
            );
            self::callWebService(null, '/saveOrgFilial', $params, 'saveOrgFilial', $loginConfig['loginClientSecret'], $loginConfig['loginUrl']);
        }
    }
    
    public static function readOAccCustom() {
        $oAccCustom = array();
        try {
            $fileDir = self::getProductBasePath() . '/modules/login/backend/config/oAccCustom.tek';
            if (file_exists($fileDir)) {
                $fileContents  = file_get_contents($fileDir);
                $fileDecrypted = self::zeedhiDecrypt($fileContents, self::LOGIN_CRYPT_STRING);
                $fileDecoded   = @json_decode($fileDecrypted, true);
                if(isset($fileDecoded['organizationId']) && is_numeric($fileDecoded['organizationId'])) {
                    $oAccCustom = $fileDecoded;
                }
            }
        } catch(\Exception $e) {}
        return !empty($oAccCustom)? $oAccCustom['organizationId'] : null;
    }    

    public static function arrayRecursiveDiff($aArray1, $aArray2) {
        $aReturn = array();

        foreach ($aArray1 as $mKey => $mValue) {
            if (\Zeedhi\Framework\Util\Functions::arrayKeyExists($mKey, $aArray2)) {
                if (is_array($mValue)) {
                    $aRecursiveDiff = self::arrayRecursiveDiff($mValue, $aArray2[$mKey]);
                    if (count($aRecursiveDiff)) { $aReturn[$mKey] = $aRecursiveDiff; }
                } else {
                    if ($mValue != $aArray2[$mKey]) {
                        $aReturn[$mKey] = $mValue;
                    }
                }
            } else {
                $aReturn[$mKey] = $mValue;
            }
        }
        return $aReturn;
    }
    
    public static function getDateIntervalInSeconds(\DateTime $initialDate, \DateTime $endDate) {
        $interval = $initialDate->diff($endDate);

        $intervalDays     = (int)$interval->format('%R%a');
        $intervalHours    = (int)$interval->format('%R%h');
        $intervalMinutes  = (int)$interval->format('%R%i');
        $intervalSeconds  = (int)$interval->format('%R%s');

        $intervalHours    = $intervalHours   + $intervalDays  * 24;
        $intervalMinutes  = $intervalMinutes + $intervalHours * 60;
        return $intervalSeconds + $intervalMinutes * 60;
    }

    public static function formatSizeUnits($bytes) {
        if ($bytes >= 1073741824) {
            $bytes = number_format($bytes / 1073741824, 2) . ' GB';
        } else if ($bytes >= 1048576) {
            $bytes = number_format($bytes / 1048576, 2) . ' MB';
        } else if ($bytes >= 1024) {
            $bytes = number_format($bytes / 1024, 2) . ' KB';
        } else if ($bytes > 1) {
            $bytes = $bytes . ' Bytes';
        } else if ($bytes == 1) {
            $bytes = $bytes . ' Byte';
        } else {
            $bytes = '0 Bytes';
        }

        return $bytes;
    }
} 