<?php

class Agro_Util {

	public $options = array();
	public $mes = array('Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro');

	const MAP_DESCRICAO_MES = [
		'01' => 'Janeiro',
		'02' => 'Fevereiro',
		'03' => 'Março',
		'04' => 'Abril',
		'05' => 'Maio',
		'06' => 'Junho',
		'07' => 'Julho',
		'08' => 'Agosto',
		'09' => 'Setembro',
		'10' => 'Outubro',
		'11' => 'Novembro',
		'12' => 'Dezembro'
	];

	
	/**
	 * Remove máscara do CAR (qualquer coisa que não seja letra/número) e padroniza para maiúsculas.
	 * Ex.: "RS-4313086-4126A9D866214140BF02F650BAC789AB" -> "RS43130864126A9D866214140BF02F650BAC789AB"
	 */
	static 	function carUnmask(string $car): string
	{
		// Remove tudo que não for alfanumérico e normaliza para maiúsculas
		$clean = preg_replace('/[^A-Za-z0-9]/', '', $car);
		return strtoupper($clean ?? '');
	}

	/**
	 * Formata o CAR (aceita com ou sem máscara na entrada).
	 * Retorna "RS-xxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".
	 */
	static function carMask(string $car): ?string
	{
		$u = self::carUnmask($car);

		$uf     = substr($u, 0, 2);      // 2 letras
		$num7   = substr($u, 2, 7);      // 7 dígitos
		$suffix = substr($u, 9);         // restante (>=1)

		return sprintf('%s-%s-%s', $uf, $num7, $suffix);
	}

	static function carDisplayValue(string $input): ?string
	{
		// Aceita tanto mascarado quanto não; retorna mascarado se válido
		return self::carMask($input);
	}


	static function calcula_coordenadas($coordenadas) {
		$cordsign = 1;
		$absdcord = 0;
		$absmcord = 0;
		$absscord = 0;

		$tmp = explode(' ', $coordenadas);
		if ($tmp[0] < 0) {
			$cordsign = -1;
		}
		$tmp[1] = abs(self::round($tmp[1] * 1000000.) / 1000000);
		$tmp[2] = abs(self::round($tmp[2] * 1000000.) / 1000000);

		$absdcord = abs(self::round($tmp[0] * 1000000.));
		$absmcord = abs(self::round($tmp[1] * 1000000.));
		$absscord = abs(self::round($tmp[2] * 1000000.));

		return self::round($absdcord + ($absmcord / 60.) + ($absscord / 3600.)) * $cordsign / 1000000;
	}

	static function coordenadas($coordenadas) {
		$vReturn = array();

		if ($coordenadas) {
			$tmp = explode(',', $coordenadas);
      		$latitude = self::calcula_coordenadas(trim($tmp[0]));
      		$longitude = self::calcula_coordenadas(trim($tmp[1]));

			$vReturn['lat'] = number_format($latitude, 8, '.', '');
			$vReturn['lon'] = number_format($longitude, 8, '.', '');
		} else {
			$vReturn['lat'] = -17.476432;
			$vReturn['lon'] = -48.779297;
		}

		return $vReturn;
	}

	static function montaLinhasTabelaIgnorandoTabelas(string $string, string $tdStyle = ''): string {
		$out = '';

		// Regex que captura blocos <table ...> ... </table> (não perfeito, mas útil em HTML bem formado)
		$pattern = '/(<table\b[^>]*>.*?<\/table>)/is';

		$parts = preg_split($pattern, $string, -1, PREG_SPLIT_DELIM_CAPTURE);

		foreach ($parts as $part) {
			if ($part === '') continue;

			if (preg_match('/^<table\b/i', $part)) {
				// É um bloco de tabela já existente: não mexer
				$out .= $part;
			} else {
				// Texto fora de tabela: converter por quebras de linha
				$normalized = str_replace(["\r\n", "\r"], "\n", $part);
				$lines = explode("\n", $normalized);

				foreach ($lines as $line) {
					$lineTrim = trim($line);
					if ($lineTrim === '') continue; // ignore linhas vazias
					// $safe = htmlspecialchars($lineTrim, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
					$out .= "<tr><td style=\"{$tdStyle}\">{$lineTrim}</td></tr>";
				}
			}
		}

		return $out;
	}

	/**
	 * Calcula a distância entre pontos geográficos
	 * 
	 * @param float $lat1 Latitude do ponto inicial em decimal
	 * @param float $lon1 Longitude do ponto inicial em decimal
	 * @param float $lat2 Latitude do ponto final em decimal
	 * @param float $lon2 Longitude do ponto final em decimal
	 * @return float Resultado do cálculo em KM
	 */
	function distancia($lat1, $lon1, $lat2, $lon2) {
		$lat1 = deg2rad($lat1);
		$lat2 = deg2rad($lat2);
		$lon1 = deg2rad($lon1);
		$lon2 = deg2rad($lon2);

		$dist = (6371 * acos( cos( $lat1 ) * cos( $lat2 ) * cos( $lon2 - $lon1 ) + sin( $lat1 ) * sin($lat2) ) );
		$dist = number_format($dist, 2, '.', '');
		return $dist;
	}

	//refactory da função distancia() que obriga a particionar as coordenadas 
	//entre latitude e longitude.
	//basta passar as coordenadas como é salva em banco no sistema
	//retorno em quilômetros
	static function recuperaDistancia($coord1, $coord2) {
		$coords = array('c1' => explode(' , ', $coord1), 'c2' => explode(' , ', $coord2));

		foreach ($coords as $part) {
			$lats[] = explode(' ', $part[0]);
			$lons[] = explode(' ', $part[1]);
		}

		return self::distancia(
			self::grau2decimal($lats[0][0], $lats[0][1], $lats[0][2]),
			self::grau2decimal($lons[0][0], $lons[0][1], $lons[0][2]),
			self::grau2decimal($lats[1][0], $lats[1][1], $lats[1][2]),
			self::grau2decimal($lons[1][0], $lons[1][1], $lons[1][2])
		);
	} 

	static function verificador($numero) {
		$numero = (string) $numero;

		$multiplicao = array();
		for ($i = 0; $i < strlen($numero); $i++) {
			$multiplicao[] = ($i % 2 == 0) ? $numero[$i] * 1 : $numero[$i] * 3;
		}

		return (ceil((array_sum($multiplicao) / 10)) * 10) - array_sum($multiplicao);
	}

	static function getUser($user) {
		if ($user) {
			$Usuarios = new Sistema_Model_Usuarios();
			return $Usuarios->getUsuario($user);
		}

		return false;
	}

	static function getUserName($idUser) {
		if ($idUser) {
			return Zend_Db_Table_Abstract::getDefaultAdapter()->fetchOne("SELECT ds_nome_usuario FROM sistema.usuarios WHERE id = $idUser");
		}

		return false;
	}

	static function getFeriadosNacionaisNoAno(int $ano): array
	{
		return Zend_Db_Table_Abstract::getDefaultAdapter()->fetchAll("SELECT * FROM obter_feriados({$ano})");
	}

	/**
	 * Funcao para comparar se uma data esta entre duas datas,
	 * retorna true caso a data a ser comparada fique entre a
	 * data inicio e a data fim. os formatos serem passados são
	 * no formato 2010-12-07
	 *
	 * @param string $comparar
	 * @param string $inicio
	 * @param string $fim
	 */
	static function checkBetweenDatas($comparar, $inicio, $fim) {
		$comparar = strtotime($comparar);
		$inicio = strtotime($inicio);
		$fim = strtotime($fim);

		if (($comparar >= $inicio) && ($comparar <= $fim)) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * Valida de uma data inicio informada é menor que
         * a data final informada.
	 *
	 * @param data $inicio dd/mm/yyyy
	 * @param data $fim dd/mm/yyyy
	*/
	static function validaDataInicioFim($inicio, $fim) {
		$iplode = explode('/',$inicio);
		$fplode = explode('/',$fim);

		list($dia, $mes, $ano) = $iplode;
		$inicio = $ano.$mes.$dia;

		list($dia, $mes, $ano) = $fplode;
		$fim = $ano.$mes.$dia;

		if ($inicio > $fim) { return false; } else { return true; }
	}

	static function getStatus($idStatus) {
		$Status = new Sistema_Model_Status();
		$Row = $Status->find($idStatus)->current();
		return $Row->ds_status;
	}

	static function getStatusChave($idStatus) {
		$Status = new Sistema_Model_Status();
		$Row = $Status->find($idStatus)->current();
		return $Row->ds_chave;
	}

	static function getIdStatus($chave, $tipoStatus = null) {
		$Status = new Sistema_Model_Status();

		if($tipoStatus){
			$tipo = " and id_tipo_status = '$tipoStatus'";
		}

		$Row = $Status->fetchRow("ds_chave = '$chave' $tipo");

		return $Row->id;
	}

	static function getChaveEstadioFenologico($id) {
		$Status = new Produto_Model_EstadiosFenologicos();
		$Row = $Status->fetchRow("id = '$id'");
		return $Row->ds_chave;
	}

	static function geraSenha($len) {
		$CaracteresAceitos = 'abcdxywzABCDZYWZ0123456789';
		$max = strlen($CaracteresAceitos) - 1;
		$password = null;

		for ($i = 0; $i < $len; $i++) {
			$password .= $CaracteresAceitos{mt_rand(0, $max)};
		}

		return strtoupper($password);
	}

	static function checkPermission($resource, $role=false) {
		if (!is_string($resource)) {
			$resource = self::getResource($resource);
		}

		$User = Zend_Auth::getInstance()->getIdentity();
		$Acl = Agro_Acl::getInstance($User);

		$role = ($role ? $role : $User->ds_chave);

		if ($Acl->has($resource)) {
			if ($Acl->isAllowed($role, $resource)) {
				return true;
			}
		}

		return false;
	}

	static function getResource(Zend_Db_Table_Row $Row) {
		if ($Row->ds_module && $Row->ds_controller && $Row->ds_action) {
			$resource = "{$Row->ds_module}:{$Row->ds_controller}:{$Row->ds_action}";
		} else if ($Row->ds_module && $Row->ds_controller && !$Row->ds_action) {
			$resource = "{$Row->ds_module}:{$Row->ds_controller}";
		} else if ($Row->ds_module && !$Row->ds_controller && !$Row->ds_action) {
			$resource = "{$Row->ds_module}";
		}

		return $resource;
	}

	static function formatCurrencyDb($valor) {

		if ($valor != '' ){
			if (strpos($valor, ',')) {
				$valor = str_replace('.', '', $valor);
				$valor = str_replace(',', '.', $valor);
			}
		} else {
			$valor = 0;
		}
		return $valor;
	}

	static function formatDbCurrency($valor, $precision=2, $decimal=',', $thousands='.') {
		if (!self::isCurrency($valor) && $valor) {
			$valor = number_format($valor, $precision, $decimal, $thousands);
		}

		return $valor;
	}

	static function isCurrency($valor) {
		return strpos($valor, ',');
	}

	static function getExtension($name) {
		return strtolower(end(explode('.', $name)));
	}

	static function getCheckNumber($NumDado, $NumDig=1, $LimMult=9) {
		$Dado = $NumDado;

		for ($n = 1; $n <= $NumDig; $n++) {
			$Soma = 0;
			$Mult = 2;
			for ($i = strlen($Dado) - 1; $i >= 0; $i--) {
				$Soma += $Mult * intval(substr($Dado, $i, 1));
				if (++$Mult > $LimMult)
					$Mult = 2;
			}

			$Dado .= strval(fmod(fmod(($Soma * 10), 11), 10));
		}

		return substr($Dado, strlen($Dado) - $NumDig);
	}

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

		if (is_array($aArray1)) {
			foreach ($aArray1 as $mKey => $mValue) {
				if (array_key_exists($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;
	}

	static function getMimeType($fileName) {
		$ext = self::getExtension($fileName);

		switch ($ext) {
			case 'jpeg':
			case 'jpe':
			case 'jpg':
				return 'image/jpeg';
				break;
			case 'gif':
				return 'image/gif';
				break;
			case 'tiff':
			case 'tif':
				return 'image/tiff';
				break;
            case 'png':
                return 'image/png';
                break;
            default:
                return 'application/octet-stream';
		}
	}

	static function isDate($date) {
		$date = explode('/', $date);
		$d = $date[0];
		$m = $date[1];
		$y = $date[2];

		$res = checkdate($m, $d, $y);
		if ($res)
			return true;
		else
			return false;
	}

	static function somarDataDiasUteis($data, $dias, $formatoDataRetorno = Zend_Date::DATES) 
	{
		if (!self::isDbDate($data)) {
			$data = self::formatDate($data, Zend_Date::W3C);
		}

		while ($dias != 0) {

			$data = date('Y-m-d', strtotime($data. ' + 1 days'));
			$ano = date('Y', strtotime($data));
			$diaSemana = date('w', strtotime($data));

			if (in_array($diaSemana, [0,6])) {
				continue;
			}

            if (in_array($data, self::getFeriadosNacionais($ano))) {
                continue;
            }

			$dias--;
		}

		return Agro_Util::formatDate($data, $formatoDataRetorno);
	}

	private function easterDate($year) {
		$a = $year % 19;
		$b = intdiv($year, 100);
		$c = $year % 100;
		$d = intdiv($b, 4);
		$e = $b % 4;
		$f = intdiv($b + 8, 25);
		$g = intdiv($b - $f + 1, 3);
		$h = (19 * $a + $b - $d - $g + 15) % 30;
		$i = intdiv($c, 4);
		$k = $c % 4;
		$l = (32 + 2 * $e + 2 * $i - $h - $k) % 7;
		$m = intdiv($a + 11 * $h + 22 * $l, 451);
		$month = intdiv($h + $l - 7 * $m + 114, 31);
		$day = (($h + $l - 7 * $m + 114) % 31) + 1;

		return mktime(0, 0, 0, $month, $day, $year);
	}


	public function getFeriadosNacionais($ano)
	{
		$feriados[] = $ano.'-01-01'; // Ano Novo;
		$feriados[] = $ano.'-04-21'; // Tiradentes;
		$feriados[] = $ano.'-05-01'; // Dia do Trabalho;
		$feriados[] = $ano.'-09-07'; // Proclamação da Independência;
		$feriados[] = $ano.'-09-20'; // Revolução Farroupilha;
		$feriados[] = $ano.'-10-12'; // Nossa Srª Aparecida;
		$feriados[] = $ano.'-11-02'; // Finados;
		$feriados[] = $ano.'-11-15'; // Proclamação da República;
		$feriados[] = $ano.'-11-20'; // Dia da Consciência Negra;
		$feriados[] = $ano.'-12-25'; // Natal;
		$pascoa = date("Y-m-d", self::easterDate($ano));
		$feriados[] = date('Y-m-d', strtotime($pascoa. ' - 2 days')); // Sexta-Feira Santa;
		$feriados[] = date('Y-m-d', strtotime($pascoa. ' - 48 days')); // Segunda de Carnaval;
		$feriados[] = date('Y-m-d', strtotime($pascoa. ' - 47 days')); // Terça de Carnaval;
		$feriados[] = date('Y-m-d', strtotime($pascoa. ' + 60 days')); // Corpus Christi;

		return $feriados;
	}

	static function somarData($data, $anos=0, $meses=0, $dias=0) {
		if (!self::isDbDate($data)) {
			$data = self::formatDate($data, Zend_Date::W3C);
		}

		$data = explode("-", $data);
		return date("Y-m-d", mktime(0, 0, 0, $data[1] + $meses, $data[2] + $dias, $data[0] + $anos));
	}

	static function isDbDate($data) {
		return strpos($data, '-');
	}

	static function isTurnoTarde ($hora){
		$Date = new Zend_Date(1234567890, false, $registryConfig['locale']);
		$Date->set($hora, Zend_Date::TIMES);

		if($Date->get(Zend_Date::HOUR) >= 12 && $Date->get(Zend_Date::HOUR) <= 20){
			return true;
		}

		return false;
	}

	static function formatDate($dt, $format='') {

		if (!$format) {
			$format = Zend_Date::DATES;
		}

		$registryConfig = Zend_Registry::get('config');

		if ($dt) {
			$Date = new Zend_Date(1234567890, false, $registryConfig['locale']);
			$Date->set($dt);

			return $Date->toString($format);
		} else {
			return null;
		}
	}

	static function joinDtVistoria($data, $hora, $minuto) {
		if ($data) {
			return Agro_Util::formatDate($data . ' ' . $hora . ' ' . $minuto, 'yyyy-MM-dd HH:mm:ss');
		} else {
			return null;
		}
	}

	static function getSchemas() {
		$Db = Agro_Db_Table_Abstract::getDefaultAdapter();

		$Rs = $Db->fetchAll("
			SELECT DISTINCT
				n.nspname as schema
			FROM
				pg_catalog.pg_class c LEFT JOIN
				pg_catalog.pg_user u ON u.usesysid = c.relowner LEFT JOIN
				pg_catalog.pg_namespace n ON n.oid = c.relnamespace
			WHERE
				c.relkind = 'r' AND
				n.nspname not in ('pg_catalog', 'public', 'information_schema')
		");

		$options = array();
		if (is_array($Rs)) {
			$options[] = '';
			foreach ($Rs as $row) {
				$options[$row['schema']] = $row['schema'];
			}
		}

		return $options;
	}

	static function getTables($schema) {
		$Db = Agro_Db_Table_Abstract::getDefaultAdapter();

		$Rs = $Db->fetchAll("
			SELECT
				c.relname as table
			FROM
				pg_catalog.pg_class c LEFT JOIN
				pg_catalog.pg_user u ON u.usesysid = c.relowner LEFT JOIN
				pg_catalog.pg_namespace n ON n.oid = c.relnamespace
			WHERE
				c.relkind in ('r', 'v') AND
				n.nspname = '$schema'
			order by
				c.relname
		");

		$options = array();
		if (is_array($Rs)) {
			$options[] = '';
			foreach ($Rs as $row) {
				$options[$row['table']] = $row['table'];
			}
		}

		return $options;
	}

	static function getColumns($table) {
		$Db = Agro_Db_Table_Abstract::getDefaultAdapter();

		$Rs = $Db->fetchAll("
			SELECT
				a.attname as column
			FROM
				pg_catalog.pg_class c LEFT JOIN
				pg_catalog.pg_user u ON u.usesysid = c.relowner LEFT JOIN
				pg_catalog.pg_namespace n ON n.oid = c.relnamespace LEFT JOIN
				pg_catalog.pg_attribute a ON c.oid = a.attrelid AND a.attnum > 0 AND a.atttypid > 0
			WHERE
				c.relname = '$table'
			order by
				c.relname

		");

		$options = array();
		if (is_array($Rs)) {
			$options[] = '';
			foreach ($Rs as $row) {
				$options[$row['column']] = $row['column'];
			}
		}

		return $options;
	}

	static function getHierarchyCombo($table, $key, $label, $order, $parent) {
		$Db = Agro_Db_Table_Abstract::getDefaultAdapter();
		$select = $Db->select();
		$select->from($table, array($key, $label));
		$select->where("$parent = ?", 0);
		$select->order($order);
		$Rs = $Db->fetchAll($select);

		if ($Rs) {
			$this->options[] = '';
			foreach ($Rs as $row) {
				$this->options[$row[$key]] = $row[$label];
				self::getComboChield($table, $key, $label, $order, $parent, $row[$key]);
			}
			return $this->options;
		} else {
			return array();
		}
	}

	static function getComboChield($table, $key, $label, $order, $parent, $id, $count=2) {
		$Db = Agro_Db_Table_Abstract::getDefaultAdapter();
		$select = $Db->select();
		$select->from($table, array($key, $label));
		$select->where("$parent = ?", $id);
		$select->order($order);
		$Rs = $Db->fetchAll($select);

		if ($Rs) {
			foreach ($Rs as $row) {
				$this->options[$row[$key]] = str_repeat('-', $count) . ' ' . $row[$label];
				self::getComboChield($table, $key, $label, $parent, $row[$key], ($count * 2));
			}
		} else {
			return array();
		}
	}

	static function montaElemento($elemento, $resposta=false, $name=false) {
		$name = ($name ? $name : "questionario[{$elemento['ds_chave_rn']}]");
		if (is_object($resposta)) {
			$resposta = $resposta->ds_resposta;
		}

		$attribs = '';
		if (array_key_exists('attrib', $elemento) && is_array($elemento['attrib'])) {
			foreach ($elemento['attrib'] as $attrib => $value) {
				$attribs = "$attrib='$value' ";
			}
		}

		$required = '';
		if ($elemento['fl_required']) {
			$required = 'element_required';
		}

		$attribs .= 'title="' . $elemento['ds_descricao_atributo'] . '"';

		switch ($elemento['ds_chave_tipo_atributo']) {
			case 'radio':
				$opcoes = self::getArrayOptions($elemento['ds_valores_opcoes']);
				ob_start();
				?>
				<table width="1%">
				<?php if (is_array($opcoes)) { ?>
						<?php foreach ($opcoes as $key => $opcao) { ?>
							<?php
							if (trim($resposta) == trim($key)) {
								$sel = 'checked';
							} else {
								$sel = '';
							}
							?>
							<tr>
								<td width="1%"><input title="<?= $elemento['ds_descricao_atributo'] ?>" <?= $sel ?> name="<?= $name ?>" type="radio" value="<?= $key ?>" id="<?= $elemento['ds_chave_rn'] ?>_<?= $key ?>" class="<?= $elemento['ds_chave_rn'] ?> <?= $required ?>" <?= $attribs ?>></td>
								<td nowrap><label for="<?= $elemento['ds_chave_rn'] ?>_<?= $key ?>"><?= $opcao ?></label></td>
							</tr>
					<?php } ?>
					<?php } ?>
				</table>
					<?php
					$input = ob_get_contents();
					ob_end_clean();
					break;
				case 'checkbox':
					$opcoes = self::getArrayOptions($elemento['ds_valores_opcoes']);
					ob_start();
					?>
				<table>
				<?php if (is_array($opcoes)) { ?>
						<?php foreach ($opcoes as $key => $opcao) { ?>
							<?php
							if ($resposta == $key) {
								$sel = 'checked';
							} else {
								$sel = '';
							}
							?>
							<tr>
								<td width="1%"><input <?= $sel ?> name="<?= $name ?>" type="checkbox" value="<?= $key ?>" id="<?= $elemento['ds_chave_rn'] ?>_<?= $key ?>" class="<?= $elemento['ds_chave_rn'] ?> <?= $required ?>" <?= $attribs ?>></td>
								<td nowrap><label for="<?= $elemento['ds_chave_rn'] ?>_<?= $key ?>"><?= $opcao ?></label></td>
							</tr>
					<?php } ?>
					<?php } ?>
				</table>
					<?php
					$input = ob_get_contents();
					ob_end_clean();
					break;
				case 'select':
					$opcoes = self::getArrayOptions($elemento['ds_valores_opcoes']);
					ob_start();
					?>
				<table>
					<tr>
						<td>
							<select name="<?= $name ?>" class="<?= $elemento['ds_chave_rn'] ?> <?= $required ?>" <?= $attribs ?>>
								<option value=""></option>
				<?php if (is_array($opcoes)) { ?>
									<?php foreach ($opcoes as $key => $opcao) { ?>
										<?php
										if ($resposta == $key) {
											$sel = 'selected';
										} else {
											$sel = '';
										}
										?>
										<option <?= $sel ?> value="<?= $key ?>"><?= $opcao ?></option>
									<?php } ?>
								<?php } ?>
							</select>
						</td>
					</tr>
				</table>
				<?php
				$input = ob_get_contents();
				ob_end_clean();
				break;

			case 'lookup':
				$sql = "select {$elemento['ds_option_value']}, {$elemento['ds_option_text']} from {$elemento['ds_schema']}.{$elemento['ds_table']}";

				if ($elemento['ds_option_filter']) {
					$Session = new Zend_Session_Namespace($elemento['ds_option_filter']);

					if ($Session->value) {
						$sql .= " where {$elemento['ds_option_filter']} = '{$Session->value}'";
					}
				}

				if ($sql) {
					$Db = Agro_Db_Table_Abstract::getDefaultAdapter();
					$Rs = $Db->fetchAll($sql);
				}

				ob_start();
				?>
				<table>
					<tr>
						<td>
							<select name="<?= $name ?>" class="<?= $elemento['ds_chave_rn'] ?> <?= $required ?>" <?= $attribs ?>>
								<option value=""></option>
				<?php if (is_array($Rs)) { ?>
									<?php foreach ($Rs as $row) { ?>
										<?php
										if ($resposta == $row[$elemento['ds_option_value']]) {
											$sel = 'selected';
										} else {
											$sel = '';
										}
										?>

										<option <?= $sel ?> value="<?= $row[$elemento['ds_option_value']] ?>"><?= $row[$elemento['ds_option_text']] ?></option>
					<?php } ?>
								<?php } ?>
							</select>
						</td>
					</tr>
				</table>
				<?php
				$input = ob_get_contents();
				ob_end_clean();
				break;

			case 'numXnum':
				$input = '<input type="text" name="' . $name . '[n]" value="' . $resposta['n'] . '" class="integer ' . $required . '" size="4"> X <input type="text" name="' . $name . '[m]" value="' . $resposta['m'] . '" class="integer" size="5" ' . $attribs . '>';
				break;


			case 'data':
				$input = '<input type="text" name="' . $name . '" value="' . $resposta . '" size="10" class="data ' . $required . '" ' . $attribs . '>';
				break;


			case 'currency':
				$input = '<input type="text" name="' . $name . '" value="' . $resposta . '" size="12" class="currency ' . $required . '" ' . $attribs . '>';
				break;


			case 'daf':
				$input = '<input type="text" name="' . $name . '" value="' . $resposta . '" size="12" class="daf ' . $required . '" ' . $attribs . ' id="daf">';
				if (Zend_Controller_Front::getInstance()->getRequest()->getModuleName() == 'atendimento') {
					$input .= '&nbsp;<button type="button" name="validadaf" id="validadaf">Verificar DAF</button>';
				}
				break;

			case 'integer':
				if($name == 'questionario[QUEST_CADPRO_VALOR]'){
				$input = '<input type="text" name="' . $name . '" value="' . $resposta . '" class="integer ' . $required . '" size="10" ' . $attribs . '>';
				}else{
				$input = '<input type="text" name="' . $name . '" value="' . $resposta . '" class="integer ' . $required . '" size="6" ' . $attribs . '>';
				}
				break;

			case 'decimal':
				$input = '<input type="text" name="' . $name . '" value="' . $resposta . '" class="decimal ' . $required . '" size="6" ' . $attribs . '>';
				break;

			case 'label':
				$input = '<label><b>' . $resposta . '</b></label>';
				break;

			case 'cpf':
				$input = '<input type="text" name="' . $name . '" value="' . $resposta . '" class="cpf ' . $required . '" size="20" ' . $attribs . '>';
				break;

			case 'text':
				$input = '<input type="text" name="' . $name . '" value="' . $resposta . '" size="30" ' . $attribs . ' class="' . $required . '">';
				break;

			default:
				$input = '<input type="text" name="' . $name . '" value="' . $resposta . '" size="15" ' . $attribs . ' class="' . $required . '">';
				break;
		}

		return $input;
	}

	static function getArrayOptions($str) {
		$ret = false;

		if (strpos($str, '|')) {
			$options = explode('|', $str);

			$ret = array();
			if (is_array($options) && count($options)) {
				foreach ($options as $option) {
					$a = explode(':', $option);
					$ret[$a[0]] = $a[1];
				}
			}
		}

		return $ret;
	}

	/**
	 * The main function for converting to an XML document.
	 * Pass in a multi dimensional array and this recrusively loops through and builds up an XML document.
	 *
	 * @param array $data
	 * @param string $rootNodeName - what you want the root node to be - defaultsto data.
	 * @param SimpleXMLElement $xml - should only be used recursively
	 * @return string XML
	 */
	static function toXml($data, $rootNodeName = 'data', $xml=null) {

		// turn off compatibility mode as simple xml throws a wobbly if you don't.
		if (ini_get('zend.ze1_compatibility_mode') == 1) {
			ini_set('zend.ze1_compatibility_mode', 0);
		}
		if ($xml == null) {
			$xml = simplexml_load_string("<?xml version='1.0' encoding='utf-8'?><$rootNodeName />");
		}

		// loop through the data passed in.
		foreach ($data as $key => $value) {
			// no numeric keys in our xml please!
			if (is_numeric($key)) {
				// make string key...
				$key = "node_" . $key;
			}
			// replace anything not alpha numeric
			//$key = preg_replace('/[^a-z]/i', '', $key);
			// if there is another array found recrusively call this function
			if (is_array($value)) {
				$node = $xml->addChild($key);
				// recrusive call.
				self::toXml($value, $rootNodeName, $node);
			} else {
				// add single node.
				$value = htmlentities($value);
				$xml->addChild($key, $value);
			}
		}
		// pass back as string. or simple xml object if you want!
		return $xml->asXML();
	}

	static function round($value, $precision=2) {
		//return round($value + 0.00001, $precision);
		return round($value, $precision);
	}

	static function importFile($path, $type, $descricao) {
		switch ($type) {
			case 'COMERCIALIZACAO':
				return self::importFileComercializacao($path, $descricao);
				break;
			case 'TAXA':
				return self::importFileTaxa($path, $descricao);
				break;
		}

		return false;
	}

	/*
	 * [0] => COD_PRODUTO
	 * [1] => DT_VENDAS_FIM
	 * [2] => DT_COBERTURA_FIM
	 * [3] => GRUPO
	 * [4] => COD_MUNICIPIO
	 */

	static function importFileComercializacao($path, $descricao) {
		$Comercializacoes = new Comercializacao_Model_Comercializacoes();
		$Importacoes = new Log_Model_Importacao();

		try {
			$Importacoes->getAdapter()->beginTransaction();

			// Salva a tabela de importacao
			$idImportacao = $Importacoes->save(array(
				'ds_arquivo' => file_get_contents($path),
				'ds_descricao' => $descricao,
				'ds_tipo_importacao' => 'COMERCIALIZACAO'
					));

			if ($idImportacao) {
				$linha = 0;
				$tmpGrupo = 0;
				$fp = fopen($path, "r");
				while (($dados = fgetcsv($fp, 0, ";")) !== false) {
					// Pula cabeçaçho
					if ($linha == 0) {
						$linha++;
						continue;
					}

					// Salva uma nova comercializacao
					if ($tmpGrupo != $dados[3]) {
						$tmpGrupo = $dados[3];

						// Salva um novo agrupamento
						$idComercializacao = $Comercializacoes->save(array(
							'id_produto' => $dados[0],
							'ds_nome_comercializacao' => date('Y') . '/' . (date('Y') + 1) . ' - ' . $dados[3],
							'dt_comercializacao_inicio' => date('d/m/Y'),
							'dt_comercializacao_fim' => $dados[1],
							'dt_cobertura_inicio' => date('d/m/Y'),
							'dt_cobertura_fim' => $dados[2],
							'tp_comercializacao' => 'M'
						));
					}

					if ($idComercializacao) {
						$Municipios = new Comercializacao_Model_ComercializacoesMunicipios();
						$Municipios->save(array(
							'id_comercializacao' => $idComercializacao,
							'id_municipio' => $dados[4]
						));
					}
				}
			} else {
				$return['message'] = "Não foi possível salvar a importação.";
				$return['status'] = false;
				return $return;
			}

			$Importacoes->getAdapter()->commit();
			$return['message'] = MSG_SUCCESS;
			$return['status'] = true;
		} catch (Exception $e) {
			$Importacoes->getAdapter()->rollBack();
			$return['message'] = $e->getMessage();
			$return['status'] = false;
		}

		return $return;
	}

	/* [0] => USUARIO
	 * [1] => PROPONENTE
	 * [2] => ID_GRUPO
	 * [3] => NOME_GRUPO
	 * [4] => PRODUTO
	 * [5] => COBERTURA
	 * [6] => FRANQUIA
	 * [7] => TAXA
	 * [8] => ESTADO
	 * [9] => MUNICIPIO
	 */

	static function importFileTaxa($path, $descricao) {
		$Agrupamentos = new Comercializacao_Model_Taxas();
		$Importacoes = new Log_Model_Importacao();
		$Valores = new Comercializacao_Model_TaxasValores();
		$return = array('status' => false);

		try {
			$Importacoes->getAdapter()->beginTransaction();

			// Salva a tabela de importacao
			$idImportacao = $Importacoes->save(array(
				'ds_arquivo' => file_get_contents($path),
				'ds_descricao' => $descricao,
				'ds_tipo_importacao' => 'TAXA'
					));

			if ($idImportacao) {
				$linha = 0;
				$tmpGrupo = 0;
				$fp = fopen($path, "r");
				while (($dados = fgetcsv($fp, 0, ";")) !== false) {
					// Pula cabeçaçho
					if ($linha == 0) {
						$linha++;
						continue;
					}

					if ($tmpGrupo != $dados[2]) {
						$tipoAgrupamento = $Agrupamentos->getTipoAgrupamento($dados);
						$tmpGrupo = $dados[2];

						// Salva um novo agrupamento
						$idAgrupamento = $Agrupamentos->save(array(
							'id_produto' => $dados[4],
							'ds_nome_agrupamento_taxas' => $dados[3] . ' - ' . $dados[2],
							'tp_taxa_agrupamento' => $tipoAgrupamento
								));
					}

					if ($idAgrupamento) {
						// Relaciona com a tabela de estado
						if ($tipoAgrupamento == 'E') {
							$Estados = new Comercializacao_Model_TaxasAgrupamentoEstados();
							$Estados->save(array(
								'id_taxa_agrupamento' => $idAgrupamento,
								'id_estado' => $dados[8]
							));
						}

						// Relaciona com a tabela de municipio
						if ($tipoAgrupamento == 'M') {
							$Municipios = new Comercializacao_Model_TaxasAgrupamentoMunicipios();
							$Municipios->save(array(
								'id_taxa_agrupamento' => $idAgrupamento,
								'id_municipio' => $dados[9]
							));
						}

						// Relaciona com a tabela de usuario
						if ($tipoAgrupamento == 'U') {
							$Usuarios = new Comercializacao_Model_TaxasAgrupamentoUsuarios();
							$Usuarios->save(array(
								'id_taxa_agrupamento' => $idAgrupamento,
								'id_usuario' => $dados[0]
							));
						}

						// Relaciona com a tabela de proponente
						if ($tipoAgrupamento == 'P') {
							$Proponentes = new Comercializacao_Model_TaxasAgrupamentoProponente();
							$Proponentes->save(array(
								'id_taxa_agrupamento' => $idAgrupamento,
								'id_proponente' => $dados[1]
							));
						}

						$idValor = $Valores->save(array(
							'id_taxa_agrupamento' => $idAgrupamento,
							'id_cobertura' => $dados[5],
							'vl_franquia' => $dados[6],
							'vl_taxa' => $dados[7],
							'vl_produtividade_estimada' => null,
							'vl_taxa_renovacao' => $dados[7],
							'vl_taxa_reduzida' => $dados[7]
								));

						if (!$idValor) {
							$return['message'] = "Não foi possível salvar o valor do agrupamento.";
							$return['status'] = false;
							return $return;
						}
					} else {
						$return['message'] = "Não foi possível salvar o agrupamento.";
						$return['status'] = false;
						return $return;
					}
				}
			} else {
				$return['message'] = "Não foi possível salvar a importação.";
				$return['status'] = false;
				return $return;
			}

			$Importacoes->getAdapter()->commit();
			$return['message'] = MSG_SUCCESS;
			$return['status'] = true;
		} catch (Exception $e) {
			$Importacoes->getAdapter()->rollBack();
			$return['message'] = $e->getMessage();
			$return['status'] = false;
		}

		return $return;
	}

	static function getThumbSize($iLenght, $iWidth, $iHeight) {
		if ($iLenght) {
			$oldWidth = $iWidth;
			$oldHeight = $iHeight;

			if (($iWidth > $iLenght) || ($iHeight > $iLenght)) {
				$iRazao = $iWidth / $iLenght;

				$width = $iLenght;
				$height = round($iHeight / $iRazao);
			} else {
				$height = $iHeight;
				$width = $iWidth;
			}

			return array('w' => $width, 'h' => $height);
		} else {
			return false;
		}
	}

	static function validarCpfCnpj($val) {
		return Agro_Validate_CpfCnpjValidate::isValid($val);
	}

	static function validarCpf($cpf) {
		return Agro_Validate_Cpf::isValid($cpf);
	}

	static function cortar($texto, $tamanho) {
		if (strlen($texto) > $tamanho) {
			return substr($texto, 0, $tamanho) . '...';
		}

		return $texto;
	}

	static function exists_in_recordset($value, $field, $rs) {
		foreach ($rs as $row) {
			if ($row[$field] == $value) {
				return true;
			}
		}

		return false;
	}

	static function informaErroAgronet($erro, $copiarUsuario = false) {
		try {
            if (APPLICATION_ENV == 'production') {
    			$ModelEmpresas = new Sistema_Model_Empresas();

    			$AgroBrasil = $ModelEmpresas->fetchRow("cpf_cnpj='03.486.745/0001-09'");
    			$Ti = $AgroBrasil->departamentos("TI");
    			$Programadores = $Ti->funcionarios();

    			$User = Zend_Auth::getInstance()->getIdentity();

    			$Date = new Zend_Date();

    			$Request = Zend_Controller_Front::getInstance()->getRequest()->getParams();

    			// $Request = Zend_Controller_Action::getRequest()->getParams();

    			$post = array();

    			foreach ($Request as $key => $value) {
    				if (!in_array($key, array("module", "controller", "action"))) {
    					$post[] = "<b>$key</b> = $value";
    				}
    			}

    			$message = '
    					<html>
    						<head>
    							<title>Agronet 2.0 - Sistema de notificações</title>
    						</head>
    						<body>
    							<h2>Prezados desenvolvedores,</h2>
    							<p style="width: 600px;">Foi detectado um erro no sistema. Por favor verifique e responda ao usuário o mais breve possível. <br/>A seguir, informações sobre o ocorrido:</p>

    							<h3>Dados do usuário</h3>
    							<p>
    								<ul>
    									<li><b>Usuário: </b>' . $User->ds_nome_usuario . '</li>
    									<li><b>Empresa: </b>' . $User->ds_nome_fantasia . '</li>
    									<li><b>Data/hora: </b>' . $Date->get("dd/MM/yyy HH:mm:ss") . '</li>
    								</ul>
    							</p>

    							<h3>Dados do sistema</h3>
    							<p>
    								<ul>
    									<li><b>Module: </b>' . $Request["module"] . '</li>
    									<li><b>Controller: </b>' . $Request["controller"] . '</li>
    									<li><b>action: </b>' . $Request["action"] . '</li>
    									<li>
    										<b>Post/Get</b>
    										<ul>
    											<li>' . implode('</li><li>', $post) . '</li>
    										</ul>
    									</li>
    								</ul>
    							</p>

    							<h3>Exception e/ou mensagem</h3>
    							<p style="width: 600px">
    								' . $erro . '
    							<p>
    						</body>
    					</html>
    				';

    			$Mail = new Agro_Mail();

				$config = array(
					'ssl' => MAIL_SSL,
					'port' => MAIL_PORT,
					'auth' => MAIL_AUTH,
					'username' => MAIL_USERNAME,
					'password' => MAIL_PASSWORD
				);

				$transport = new Zend_Mail_Transport_Smtp(MAIL_SMTP, $config);
				$Mail->setDefaultTransport($transport);

				//já está setado na config do construct do objeto Zend_Mail_Transport_Smtp
    			//$Mail->setFrom("ti@agrobrasilseguros.com.br", "AgroNet 2.0 - Sistema de notificação");

    			$Mail->setSubject("AgroNet 2.0 - ERRO NO SISTEMA");

    			$Responsavel = $Ti->responsavel();
    			$Mail->addTo($Responsavel["ds_email"], $Responsavel["ds_nome_funcionario"]);

    			foreach ($Programadores as $Funcionario) {
    				if ($Funcionario["id"] != $Responsavel["id"]) {
    					if ($Funcionario["ds_email"]) {
    						$Mail->addCc($Funcionario["ds_email"], $Funcionario["ds_nome_funcionario"]);
    					}
    				}
    			}

    			if ($copiarUsuario) {
    				$Mail->addCc($User->ds_email, $User->ds_nome_funcionario);
    			}

    			$Mail->setBodyHtml($message);

    			$Mail->send();
			}
		} catch (Exception $e) {
			dump($e->getMessage());
		}
	}

	static function setNotificacao($titulo, $mensagem, $para, $cc=false) {
		try {
			$Model = new Sistema_Model_Notificacoes();

			$dest = false;

			if ($cc) {
				$dest = array();
				if (is_array($cc)) {
					$dest = $cc;
				} else {
					$dest[] = $cc;
				}
			}
      
      $User = Zend_Auth::getInstance()->getIdentity();
      $Date = new Zend_Date();
      $Request = Zend_Controller_Front::getInstance()->getRequest()->getParams();

      $post = [];

      foreach($Request as $key => $value) {
        if (!in_array($key, ['module','controller','action','error_handler'])) {
          $post[] = "<b>$key</b> = $value";
        }
      }
      
      $body = '
        <html>
          <head>
            <title>Agronet 2.0 - Sistema de notificações</title>
          </head>
          <body>
            <h2>Prezados desenvolvedores,</h2>
            <p style="width: 600px;">Foi detectado um erro no sistema. Por favor verifique e responda ao usuário o mais breve possível. <br />A seguir, informações sobre o ocorrido:</p>
            
            <h3>Dados do usuário</h3>
            <p>
              <ul>
                <li><b>Usuário: </b>' . $User->ds_nome_usuario . '</li>
                <li><b>Data/hora: </b>' . $Date->get("dd/MM/yyyy HH::mm:ss") . '</li>
              </ul>
            </p>

            <h3>Dados do sistema</h3>
            <p>
              <ul>
                <li><b>Module: </b>' . $Request['module'] . '</li>
                <li><b>Controller: </b>' . $Request['controller'] . '</li>
                <li><b>Action: </b>' . $Request['action'] . '</li>
                <li>
                  <b>Parâmetros usados (Post/Get)</b>
                  <ul>
                    <li>' . implode('</li><li>', $post) . '</li>
                  </ul>
              </ul>
            </p>

            <h3>Exception e/ou mensagem</h3>
            <p style="width: 600px">
              ' . $mensagem . '
            </p>
          </body>
        </html>
      ';

			$Mail = new Zend_Mail("UTF-8");

			$config = array(
					'ssl' => MAIL_SSL,
					'port' => MAIL_PORT,
					'auth' => MAIL_AUTH,
					'username' => MAIL_USERNAME,
					'password' => MAIL_PASSWORD
			);

			if (APPLICATION_ENV != 'production') {
				$body .= "<br><br><b>ATENÇÃO: ESTA MENSAGEM FOI ENVIADA EM AMBIENTE DE TESTE, FAVOR DESCONSIDERÁ-LA.</b>";
			}

			$transport = new Zend_Mail_Transport_Smtp(MAIL_SMTP, $config);
			$Mail->setDefaultTransport($transport);

			$Mail->setFrom("ti@agrobrasilseguros.com.br", "Agronet - Sistema de notificação");

			$Mail->setSubject($titulo);
			$Mail->setBodyHtml($body);

			$Mail->addTo($para);

			$Model = new Sistema_Model_Funcionarios();

			if ($dest) {
				foreach ($dest as $id) {
					$Funcionario = $Model->fetchRow("id_usuario=$id");
					$Mail->addCc($Funcionario->ds_email);
				}
			}

			$Mail->send();

		} catch (Exception $e) {
      Agro_Util::zf_debug($e->getMessage());
			dump($e->getMessage());
		}
	}

	static function array_pairs($array, $key, $value) {
		$tmp = array();

		if (is_array($array) && count($array)) {
			foreach ($array as $row) {
				$tmp[$row[$key]] = $row[$value];
			}
		}

		return $tmp;
	}

	static function status($chave, $grupo = null) {
		$Model = new Sistema_Model_Status();
		return $Model->getId($chave, $grupo);
	}

	static function contarDiasEntreDatas($dt1, $dt2, $format = 'd/M/Y') {
		$Dt1 = new Zend_Date($dt1, $format);
		$Dt2 = new Zend_Date($dt2, $format);

		$dif = $Dt2->get(Zend_Date::TIMESTAMP) - $Dt1->get(Zend_Date::TIMESTAMP);

		return floor((($dif / 60) / 60) / 24);
	}

	static function buscaValorConfig($chave, $modulo="sistema"){
		$sql = 'select ds_valor from '.$modulo.'.config where ds_chave = "'.$chave.'"';
		return Zend_Db_Table::getDefaultAdapter()->fetchOne($sql);
	}

	static function geraSalvaXml($nomeArquivo, $msg) {
	    $file = fopen(APPLICATION_PATH."/upload_files/xml_transmissao_error/{$nomeArquivo}", "w+");
	    fwrite($file, $msg);
	    fclose($file);
	}

	static function geraSalvaXmlSinistro($idAviso, $nomeArquivo, $msg) {
		$file = fopen(APPLICATION_PATH."/upload_files/xml_transmissao_error/{$nomeArquivo}", "a+");
		fwrite($file, $msg);
		fclose($file);
	}

	static function formataNome(string $nome): string
	{
		$arr = explode(' ', $nome);
		$nome = '';

		foreach ($arr as $val) {
			$nome .= ucfirst(strtolower($val)) . ' ';
		}

		return trim($nome);
	}

	/**
	 * Converte coordenadas de DMS (0°,0',0'') para DEC (decimal)
	 * @param int $deg (grau)
	 * @param int $min (minuto)
	 * @param int $sec (segundo)
	 * @return float - O valor em decimal
	 * @access public
	 */
	static function grau2decimal($deg, $min, $seg, $bcScale = 6) {
		bcscale($bcScale);
		$converted_min = bcdiv(number_format($min,$bcScale),60);
		$converted_seg = bcdiv(number_format($seg,$bcScale),3600);

		//retorno multiplicado por -1 para inversão do sinal visto que apenas território brasileiro
		//são aceitos (W,S)
		return bcmul(bcadd(abs(number_format($deg,$bcScale)),bcadd($converted_min,$converted_seg)),-1);
	}

	/**
	 * Retorna o nome do município (sem acentos e em maiúsculo) conforme coordena passada
	 * @param String $coordenada (longitude em decimal)
	 * @param stdClass $latitudeLongitude - {['latitude'] => -23.954731844115, ['longitude'] => -49.100754537737})
	 * @return String
	 * @access public
	 */
	public function getMunicipioByCoordenada($coordenada, $isLongitudeLatitude = false) {

		if (!$isLongitudeLatitude) {
			$coordenadas = explode(',', $coordenada);
			$lat = explode(' ',trim($coordenadas[0]));
			$lon = explode(' ',trim($coordenadas[1]));

			list($deg, $min, $seg) = $lat;
			$converted_lat = self::grau2decimal($deg, $min, $seg);
			list($deg, $min, $seg) = $lon;
			$converted_lon = self::grau2decimal($deg, $min, $seg);

		} else {
			$converted_lat = $coordenada->latitude;
			$converted_lon = $coordenada->longitude;
		}

		$file_json = file_get_contents("https://maps.google.com/maps/api/geocode/json?latlng=".
				$converted_lat.",".$converted_lon.
				"&sensor=false&radius=1&key=" . GOOGLE_MAPS_API);
		$json = json_decode($file_json,true);



		$resultado = array();
		foreach ($json['results'] as $result) {
			$location_type = $result['geometry']['location_type'];

			foreach ($result['address_components'] as $endereco) {
				if ($endereco['types'][0] == 'administrative_area_level_2') {
					$resultado[$location_type][] = strtoupper(self::removeAcentos(trim($endereco['long_name'])));
				}
			}
		}

		if (array_key_exists('ROOFTOP', $resultado)) {
			return $resultado['ROOFTOP'][0];
		}

		if (array_key_exists('APPROXIMATE', $resultado)) {
			return $resultado['APPROXIMATE'][0];
		}

		if (array_key_exists('GEOMETRIC_CENTER', $resultado)) {
			return $resultado['GEOMETRIC_CENTER'][0];
		}

		return '';
	}

	/**
	 * Remove acentos
	 * @param String $texto
	 * @return string
	 */
	public static function removeAcentos($texto){
		return strtr(utf8_decode($texto), utf8_decode('àÀáÁâÂãÃäÄáèÈéÉêÊíÍìÌóÓòÒõÕôÔúÚùÙçÇ'), utf8_decode('aAaAaAaAaAaeEeEeEiIiIoOoOoOoOuUuUcC'));
	}

	public function debug($var) {
		echo "<pre>";
		var_dump($var);
		echo "</pre>";
	}

	static function getTipoObservacao($idTipoObs) {
		$Obs = new Sinistro2_Model_TipoObservacao();
		$Row = $Obs->find($idTipoObs)->current();
		return $Row->ds_tipo_observacao;
	}

    /*
     * exibe debug da variável no arquivo de log
     * @param $debug - a variável a ser debugada (requerida)
     * @param $style - o tipo de mensagem (ERR, ALERT, CRIT, DEBUG, EMERG, INFO, NOTICE, WARN)
     * Se style não for passada, assume-se INFO como style padrão.
     */
    static function zf_debug($debug, $style = '', bool $habilitarDebugTrace = true)
    {
        if (ENABLE_DEBUG) {
            ob_start();

            if ($habilitarDebugTrace) {
                $debugTrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
                $fileDebug = "[{$debugTrace[0]['file']}:{$debugTrace[0]['line']}]";

                if (array_key_exists('class', $debugTrace[1])) {
                    $fileDebug = "[{$debugTrace[1]['class']}{$debugTrace[1]['type']}{$debugTrace[1]['function']}()";
                    $fileDebug .= ":{$debugTrace[0]['line']}]";
                }

                print_r($fileDebug);
                echo ": ";
            }

            print_r($debug);
            $debug = ob_get_clean();
            $logger = Zend_Registry::get('logger');
            return $logger->log($debug, ($style ? Zend_Log::$style : Zend_Log::INFO));
        }
        return true;
    }
    
    static function formataData( $dtData ){
       	$ano = substr( $dtData, 0, 4 );
       	$mes = substr( $dtData, 5, 2 );
       	$dia = substr( $dtData, 8, 2 );

       	$dtDataFormatada = $ano.'-'.$mes.'-'.$dia;
		
       	return $dtDataFormatada;
    }

    /**
     * Exibe erros encontrados ao validar um arquivo XML
     */
    static function checkXML() {
    	$return = "<style>
    						ul#example4 {
							   list-style: none;
							   margin: 1em 0;
							   padding: 0;
							}
							ul#example4 li {
							   margin: 0;
							   padding: 3px 10px 5px 20px;
							   color: #000;
							}
							ul#example4 li:hover {
							   color: #000;
							   background-color: #ddd;
							}
				</style>";

    	$errors = libxml_get_errors();

		$return .= "&nbsp;&nbsp;&nbsp;&nbsp;<b>Detalhe da análise</b><br/><ul id='example4'>";
    	foreach ($errors as $error) {

    		switch ($error->level) {
	            case LIBXML_ERR_WARNING:
	                $return .= "<li><b>Atenção $error->code</b>: ";
	                break;
	            case LIBXML_ERR_ERROR:
	                $return .= "<li><b>Erro $error->code</b>: ";
	                break;
	            case LIBXML_ERR_FATAL:
	                $return .= "<li><b>Erro fatal $error->code</b>: ";
	                break;
    		}
    		$return .= trim($error->message);
    		$info = new SplFileInfo($error->file);

    		if ($info->isFile()) {
    			$return .= "  <b>$error->file</b>";
    		}
    		$return .= " on line <b>$error->line</b></li>";
	   	}

	   	$return .= "</ul>";

    	libxml_clear_errors();

    	return $return;
    }

    /**
     * Converte um Objeto XML (SimpleXMLElement) em array, recursivamente
     * @param $object: objeto SimpleXMLElement
     * @return array
	*/
    static function XMLObject_to_Array($object) {
    	if (is_object($object)) $object = (array) $object;

    	if (is_array($object)) {
    		$new = array();
    		foreach ($object as $key => $value) {
    			$new[$key] = self::XMLObject_to_Array($value);
    		}
    	} else {
    		$new = $object;
    	}

    	return $new;
    }

    /**
     * Retorna o tipo de imagem de um string base64
     * @param $str: string base64 (imagem)
     * @return String or false
    */
    static function getBase64ImageExtension($str) {
    	$imgdata = base64_decode($str);
    	$f = finfo_open();
    	$mime_type = finfo_buffer($f, $imgdata, FILEINFO_MIME_TYPE);

    	switch ($mime_type) {
    		case 'image/jpeg':
    			return 'jpg';
    			break;
    		case 'image/png':
    			return 'png';
    		default:
    			return false;
    			break;
    	}
    }
    
    /*
     * Redimensiona a imagem para se adaptar e mostrar o croqui.
     */
    static function imageRezise($width, $height, $default=880) {
    	//$default valor baseado no croqui no view da proposta
    	
    	$scale = $default/$width;
    	$new_height = intval($height * $scale);
    	$new_width = $default;
    	
    	return array('width' => $new_width, 'height' => $new_height);
    }

    static function translateNivelTecnologico($nivel) {
    	switch ($nivel) {
    		case 'irregular':
    		case 1:
    			return 'Irregular';
    			break;
    		case 'regular':
    		case 2:
    			return 'Regular';
    			break;
    		case 'bom':
    		case 3:
    			return 'Bom';
    			break;
    		case 'otimo':
    		case 4:
    			return 'Ótimo';
    			break;
    		default:
    			return '';
    			break;
    	}
    }

    /*
     * Converte uma imagem para um determinado formato
     * Exemplo de chamada:
     * Agro_Util::convertImage(
     * 		'imagem.svg',
     *      'png24',
     *      '/var/www/dev/agronet/application/upload_files/empresas/',
     *      '985',
     *      '760',
     * 		'/var/www/dev/agronet/application/upload_files/empresas/',
     * )
     * 
     * @return boolean
     */
    static function convertImage($filename, $format, $pathOutput, $resolutionX, $resolutionY, $pathInput = '', $source= '') {
    	if (!empty($pathInput)) {
    		$usmap = $pathInput.$filename;
    		$fileInput = file_get_contents($usmap);
    	} else {
    		$fileInput = $source;
    	}
    	
	$im = new Imagick();
	$im->clear();

        $im->readImageBlob($fileInput);
        $im->setResolution($resolutionX,$resolutionY);

        $im->setImageFormat($format);

        return $im->writeImage($pathOutput.$filename);
    }

    static function getPrioridadeConferenciaLVP001AsString($prioridadeConferencia) {
    	switch ($prioridadeConferencia) {
    		case 1:
    			return 'Sinistro';
    			break;
    		case 2:
    			return 'Vistoria sem Assinatura';
    			break;
    		case 3:
    			return 'Cancelamento';
    			break;
    		case 4:
    			return 'Zoneamento';
    			break;
    		case 5:
    			return 'Aumento da Área';
    			break;
    		case 6:
    			return 'Redução da Área';
    			break;
    		case 7:
    			return 'Redução do Rendimento';
    			break;
    		case 8:
    			return 'Unificação/Distribuição';
    			break;
    		case 9:
    			return 'Alteração das Coordenadas';
    			break;
    		case 10:
    			return 'Sem Prioridade';
    			break;
    		default:
    			return '';
    			break;
    	}
    }

    static function checkPermissionRTInfos() {
    	$user = Zend_Auth::getInstance()->getIdentity();

    	if ($user->id_empresa == 20) {
    		return true;
    	}

    	return false;
	}
	
	static function generateAtscript($script, $params=array(), $date = '', $letter = null) {
      if (PHP_OS == 'Linux') {
        $file = '/tmp/executa_at_'.rand().'.at';
        $dir = substr($_SERVER['DOCUMENT_ROOT'],0,-7).'Curl/'.$script;
      }

      $cmd = '/usr/bin/php '.$dir.' '.implode(" ", $params)."\n";
      $cmd .= 'rm -fr '.$file;
		
		  file_put_contents($file, $cmd);
      $date = !empty($date) ? $date : "now + 2 minutes";

	  if (!empty($letter)) {
		$letter = " -q {$letter} ";
	  }

      shell_exec("at {$letter} -f {$file} {$date}");
	}

	static function hasAtByLetter($letter)
	{
		$retorno = shell_exec("atq | egrep '{$letter}\s(root|www-data)'");
		return !empty($retorno);
	}

	/** 
	* Transforma coordenada de decimal para graus, minutos e segundos
	*/
	static function dec2gms(float $decimal) : string {
		$abs = abs($decimal);
		$graus = floor($abs);
		$segundos = ($abs - $graus) * 3600;
		
		$minutos = floor($segundos / 60);
		$segundos = round($segundos - ($minutos * 60),2);

		$partesSegundos = explode('.', $segundos);
    	$segundos = str_pad($partesSegundos[0], 2, '0', STR_PAD_LEFT);
		
    	if (!empty($partesSegundos[1])) {
    	    $segundos .= ".{$partesSegundos[1]}";
    	}

		$minutos = str_pad($minutos, 2, '0', STR_PAD_LEFT);
	
		return '-'.($graus).' '.($minutos).' '.($segundos);
	}

	public static function datesOverlap($dataInicio1, $dataFim1, $dataInicio2, $dataFim2)
  {
      $dataInicio1 = strtotime($dataInicio1);
      $dataFim1 = strtotime($dataFim1);
      $dataInicio2 = strtotime($dataInicio2);
      $dataFim2 = strtotime($dataFim2);

      return $dataInicio1 <= $dataFim2 && $dataFim1 >= $dataInicio2;
  }

  public static function mascararNome(string $nome) : string
  {
      $nome = explode(" ", $nome);
      return $nome[0] . str_repeat('.', 20);
  }

  public static function mascararCpf(string $cpf) : string
  {
      $inicioCpf = explode('.', $cpf);
      $fimCpf = explode('-', $cpf);

      return "{$inicioCpf[0]}........-{$fimCpf[1]}";
  }

  public static function validaDir(string $path) : bool {
	if ($dir = opendir(APPLICATION_PATH.'/upload_files')) {
		while (($folder = readdir($dir)) != false) {
			if ($path == $folder) {
				return true;
			}
		}
	}
	return false;
  }

    /**
     * Valida se a variável é de determinado tipo. Se true, retorna a própria variável, senão retorna false
     * @param $variable
     * @param int|null $tipoFiltro
     * @return mixed
     */
  public static function filterVariable($variable, ?int $tipoFiltro = FILTER_VALIDATE_INT)
  {
      return filter_var($variable, $tipoFiltro);
  }

  public static function processarRestricoes(&$restricoes, $modelRestricoesCriterios)
  {

	foreach ($restricoes as $index => $restricao) {

        $configuracoes = $modelRestricoesCriterios->getCriteriosVinculados($restricao['id']);
        $configuracoes = $configuracoes->toArray();
		
        if (empty($configuracoes)) {
            unset($restricoes[$index]);
        } else {
            $restricoes[$index]['configuracao'] = $configuracoes;
        }
		
    }

  }

    public static function removerCaracteresQuebraRelatorios(?string $string, string $replacement = ''): string
    {
        return preg_replace("/\r|\n|;/", $replacement, $string);
    }

    public static function escaparHtmlComExcecoes($html)
    {
        $placeholders = [];
        $tagsPermitidas = ['b', 'u', 'i', 'strong', 'br', 'p'];

        foreach ($tagsPermitidas as $tag) {
            $html = preg_replace_callback("/(<\/?$tag\b[^>]*>)/i", static function ($matches) use (&$placeholders, $tag) {
                $original = $matches[0];

                if (preg_match("/^<\//", $original)) {
                    $tagAjustada = "</{$tag}>";
                } else {
                    $tagAjustada = "<{$tag}>";
                }

                $key = '__PLACEHOLDER_' . count($placeholders) . '__';
                $placeholders[$key] = $tagAjustada;
                return $key;
            }, $html);
        }

        $html = htmlspecialchars($html, ENT_QUOTES);

        foreach ($placeholders as $key => $originalTag) {
            $html = str_replace($key, $originalTag, $html);
        }

        return $html;
    }

	public static function formatarCpfCnpj(string $cpfCnpj): string
	{
    	$cpfCnpj = Agro_Validate_CnpjAlpha::normalize($cpfCnpj);

    	if (strlen($cpfCnpj) === 11) {
    	    return Agro_Validate_Cpf::format($cpfCnpj);
    	} elseif (strlen($cpfCnpj) === 14) {
			return Agro_Validate_CnpjAlpha::format($cpfCnpj);
    	}

    	return '';
	}
	
	function proximoDiaUtil($data = 'now', string $timezone = 'America/Sao_Paulo', array $feriados = []): DateTime
	{
		
    	$tz = new DateTimeZone($timezone);
    	$dt = $data instanceof DateTime ? clone $data : new DateTime($data, $tz);
    	$dt->setTimezone($tz);
		if(empty($feriados)){
			$feriados = $this->getFeriadosNacionais($dt->format('Y'));
		}
		
    	while (true) {
        	$diaSemana = (int)$dt->format('N'); 
        	$yyyymmdd  = $dt->format('Y-m-d');

        	$ehFds = ($diaSemana >= 6); 
        	$ehFeriado = in_array($yyyymmdd, $feriados, true);

        	if (!$ehFds && !$ehFeriado) {
               	return $dt;
        	}
        	
        	$dt->modify('+1 day');
    	}
	}

    /**
     * Converte latitude/longitude decimais em uma string DMS exatamente no formato:
     *   26°56'11"S, 51°19'17"W
     *
     * Regras:
     * - Hemisfério automático: lat < 0 => S, lat >= 0 => N; lon < 0 => W, lon >= 0 => E
     * - Minutos e segundos com zero à esquerda (2 dígitos)
     * - Segundos arredondados ao inteiro mais próximo (com carry para minuto/grau)
     *
     * @param float $latitude Latitude em decimal (ex.: -26.93638889)
     * @param float $longitude Longitude em decimal (ex.: -51.32138889)
     * @return array
     */
    public static function convertDecimalToDMSString(float $latitude, float $longitude): array
    {
        $formatar = function (float $valor, string $tipo): string {
            $abs = abs($valor);

            // Graus
            $graus = (int)floor($abs);
            $rem = ($abs - $graus) * 60.0;

            // Minutos
            $minutos = (int)floor($rem);
            $segundos = ($rem - $minutos) * 60.0;

            // Arredonda segundos para inteiro e trata carry
            $segundos = (int)round($segundos);
            if ($segundos >= 60) {
                $segundos = 0;
                $minutos++;
            }
            if ($minutos >= 60) {
                $minutos = 0;
                $graus++;
            }

            // Hemisfério
            if ($tipo === 'lat') {
                // Validação simples de faixa dos graus
                if ($graus > 90) {
                    throw new InvalidArgumentException("Latitude fora do intervalo válido (graus 0–90).");
                }
                $hemisferio = ($valor < 0) ? 'S' : 'N';
            } elseif ($tipo === 'lon') {
                if ($graus > 180) {
                    throw new InvalidArgumentException("Longitude fora do intervalo válido (graus 0–180).");
                }
                $hemisferio = ($valor < 0) ? 'W' : 'E';
            } else {
                throw new InvalidArgumentException("Tipo inválido.");
            }

            // Zero-padding para minutos e segundos
            $minutosFinal = str_pad((string)$minutos, 2, '0', STR_PAD_LEFT);
            $segundosFinal = str_pad((string)$segundos, 2, '0', STR_PAD_LEFT);

            return "{$graus}°{$minutosFinal}'{$segundosFinal}\"{$hemisferio}";
        };

        $latitudeString = $formatar($latitude, 'lat');
        $longitudeString = $formatar($longitude, 'lon');

        return [
          'latitude' => $latitudeString,
          'longitude' => $longitudeString,
        ];
    }

    public static function retornarSomenteNumeros(string $valor): string
    {
        return preg_replace('/\D/', '', $valor);
    }

	/**
	* Verifica se uma string numérica representa um número maior que zero,
	* considerando o formato brasileiro (pt-BR), onde:
	* - Separador de milhar é ponto (.)
	* - Separador decimal é vírgula (,)
	*
	* Exemplos válidos:
	*  - "123"
	*  - "1.234"
	*  - "1.234.567"
	*  - "1.234,56"
	*  - "0,5"
	*
	* Exemplos inválidos:
	*  - "1,234.56" (formato en-US)
	*  - "abc"
	*  - "" (string vazia)
	*
	* @param string $s A string a ser validada e convertida.
	*
	* @return bool Retorna true se a string representa um número maior que zero,
	*              false caso contrário (incluindo valores inválidos ou <= 0).
	*/
	public static function isNumeroMaiorQueZero(string $s): bool
	{
    	$s = trim($s);
    	if ($s === '') return false;

    	// Padrão pt-BR: milhar com ponto, decimal com vírgula.
    	// Exemplos válidos: "123", "1.234", "1.234.567", "1.234,56", "0,5"
    	$pattern = '/^[+-]?(?:\d{1,3}(?:\.\d{3})+|\d+)(?:,\d+)?$/';

    	if (!preg_match($pattern, $s)) return false;

    	// Remove separador de milhar e troca vírgula por ponto
    	$normalized = str_replace(['.', ','], ['', '.'], $s);

    	return (float)$normalized > 0.0;
	}

	public static function esconderCpf(string $cpf): string
	{
		$cpf = preg_replace('/\D/', '', $cpf);
		
		if (strlen($cpf) === 11) {
			return '***.' . substr($cpf, 3, 3) . '.' . substr($cpf, 6, 3) . '-**';
		}

		return $cpf;
	}
}
