# -*- coding: utf-8 -*-

"""
/***************************************************************************
 GeoINCRA
                                 A QGIS plugin
 Georreferenciamento de Imóveis Rurais
 Generated by Plugin Builder: http://g-sherman.github.io/Qgis-Plugin-Builder/
                              -------------------
        begin                : 2022-02-13
        copyright            : (C) 2022 by Tiago Prudencio e Leandro França
        email                : contato@geoone.com.br
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
"""

__author__ = 'Tiago Prudencio e Leandro França'
__date__ = '2025-05-29'
__copyright__ = '(C) 2025 by Tiago Prudencio e Leandro França'

from qgis.PyQt.QtCore import QCoreApplication
from qgis.core import (QgsProcessingException,
                       QgsProcessingAlgorithm,
                       QgsProcessingParameterEnum,
                       QgsCoordinateReferenceSystem,
                       QgsProcessingParameterFile,
                       QgsProcessingParameterFileDestination,
                       QgsProcessingParameterNumber)

from qgis.PyQt.QtGui import QIcon
from .Funcs import LerPDF, str2HTML
import os
from datetime import datetime

class ConversorMemorial(QgsProcessingAlgorithm):

    PDF = 'PDF'
    PERIMETRO = 'PERIMETRO'
    HTML = 'HTML'
    HTML2 = 'HTML2'
    COORD = 'COORD'
    ANEL = 'ANEL'
    CONFRONT = 'CONFRONT'

    def tr(self, string):
        return QCoreApplication.translate('Processing', string)

    def createInstance(self):
        return ConversorMemorial()

    def name(self):
        return 'ConversorMemorial'.lower()

    def displayName(self):
        return self.tr('a. Conversor de Memorial do Sigef para Cartórios')

    def group(self):
        return self.tr('5. 🔄 Conversão e Integração')

    def groupId(self):
        return 'conversao_integracao'

    def icon(self):
        return QIcon(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'images/geoincra_pb.png'))
    
    def tags(self):
        return 'GeoOne,GeoRural,INCRA,Sigef,memorial,pdf,conversão,tranformar,textual,tabular,descritivo,documento,cartório,matrícula,regularização,fundiária'.split(',')
    

    def shortHelpString(self):
        txt = '''Converte automaticamente o memorial descritivo tabular do SIGEF (PDF) em um texto narrativo mais fluido, mantendo os elementos técnicos exigidos, com formato adequado para leitura e uso em cartórios de registro de imóveis.
        Ideal para complementar o memorial tabular conforme exigências legais ou práticas cartorárias.'''

        footer = '''<div>
                      <div align="center">
                      <a target="_blank" rel="noopener noreferrer" href="https://geoone.com.br/pvgeoincra/"><img title="Inscreva-se no curso de GeoINCRA" style="width: 100%; height: auto;" src="'''+ os.path.join(os.path.dirname(os.path.dirname(__file__)), 'images/INCRA_GeoOne.jpg') +'''"></a>
                      </div>
                      <div align="right">
                      <p align="right">
                      <a href="https://geoone.com.br/pvgeoincra/"><span style="font-weight: bold;">Conheça o curso de GeoINCRA no QGIS</span></a>
                      </p>
                      <p align="right">
                      <a href="https://portal.geoone.com.br/m/lessons/geoincra?classId=5814"><span style="font-weight: bold;">Acesse a aula sobre esta ferramenta no curso de GeoINCRA no GeoOne</span></a>
                      </p>
                      <a target="_blank" rel="noopener noreferrer" href="https://geoone.com.br/"><img title="GeoOne" width="280"  src="'''+ os.path.join(os.path.dirname(os.path.dirname(__file__)), 'images/GeoOne.png') +'''"></a>
                      <p><i>"Mapeamento automatizado, fácil e direto ao ponto é na GeoOne!"</i></p>
                      </div>
                    </div>'''
        return txt + footer

    def initAlgorithm(self, config=None):

        self.addParameter(
        QgsProcessingParameterFile(
            self.PDF,
            self.tr('Memorial Tabular do Sigef (PDF)'),
            fileFilter= 'Arquivo PDF (*.pdf)'
            )
        )

        opcoes = [self.tr('(lon,lat,h)'),
                  self.tr('(lat,lon,h)'),
                  self.tr('(lon,lat)'),
                  self.tr('(lat,lon)'),
                  '(lon,lat,h)' + self.tr(' com sufixo'),
                  '(lat,lon,h)' + self.tr(' com sufixo'),
                  '(lon,lat)' + self.tr(' com sufixo'),
                  '(lat,lon)' + self.tr(' com sufixo')
               ]

        self.addParameter(
            QgsProcessingParameterEnum(
                self.COORD,
                self.tr('Padrão de Coordenadas'),
				options = opcoes,
                defaultValue= 5
            )
        )

        confront = ['Apenas Nome',
                    'Nome e Matrícula',
                    'Nome, Matrícula e CNS',
                    'CNS, Matrícula e Nome'
               ]

        self.addParameter(
            QgsProcessingParameterEnum(
                self.CONFRONT,
                self.tr('Descrição dos confrontantes'),
				options = confront,
                defaultValue= 0
            )
        )

        self.addParameter(
            QgsProcessingParameterNumber(
                self.ANEL,
                self.tr('Anel'),
                type = QgsProcessingParameterNumber.Type.Integer,
                minValue = 1,
                optional = True
                )
            )
        
        self.addParameter(
            QgsProcessingParameterFileDestination(
                self.HTML2,
                self.tr('Memorial Sintético ( Tabular )'),
                self.tr('HTML files (*.html)')
            )
        )

        self.addParameter(
            QgsProcessingParameterFileDestination(
                self.HTML,
                self.tr('Memorial Descritivo ( Textual )'),
                self.tr('HTML files (*.html)')
            )
        )


    def processAlgorithm(self, parameters, context, feedback):

        pdf_path = self.parameterAsString(
            parameters,
            self.PDF,
            context
        )

        coordenadas = self.parameterAsEnum(
            parameters,
            self.COORD,
            context
        )

        tipoDescrConfront = self.parameterAsEnum(
            parameters,
            self.CONFRONT,
            context
        )

        anel = self.parameterAsInt(
            parameters,
            self.ANEL,
            context
        )

        if pdf_path is None:
            raise QgsProcessingException(self.invalidSourceError(parameters, self.PDF))


        # Sistema de Referência de Coordenadas
        SRC = QgsCoordinateReferenceSystem('EPSG:4674')

        # Ler PDF
        dic, lista_cod, dic_cod, ind_encravado = LerPDF(pdf_path, feedback = feedback)


        if len(lista_cod) == 0 or dic['Denominação:'] == '':
            raise QgsProcessingException('PDF de entrada não é um Memorial do Sigef!')
        
        feedback.pushInfo('Alimentando arquivo HTML...')

        # Se encravado, fatiar lista_cod
        def fatiar_lista(a, ind):
            ind = [0] + ind + [len(a)]
            return [a[ind[i]:ind[i+1]] for i in range(len(ind)-1)]

        if len(ind_encravado) > 0:
            listas_fat = fatiar_lista(lista_cod, ind_encravado)
        else:
            listas_fat = [lista_cod]


        # Escolher anel
        if anel:
            if anel <= len(listas_fat):
                ind = anel-1
            else:
                raise QgsProcessingException('Valor inválido para o número do anel!')
        else:
            ind = 0
        lista_cod_fat = listas_fat[ind]


        # Modelo de coordenadas
        def CoordN (x, y, z):
            if coordenadas > 3: # com sufixo
                x = x[1:]+'W'
                y = y[1:]+'S' if y[0] == '-' else y[1:]+'N'
            if coordenadas == 0:
                txt = '''<b>longitude [Xn]</b>, <b>latitude [Yn]</b> e <b>h [Zn]m</b>'''
            elif coordenadas == 1:
                txt = '''<b>latitude [Yn]</b>, <b>longitude [Xn]</b> e <b>h [Zn]m</b>'''
            elif coordenadas == 2:
                txt = '''<b>longitude [Xn]</b> e <b>latitude [Yn]</b>'''
            elif coordenadas == 3:
                txt = '''<b>latitude [Yn]</b> e <b>longitude [Xn]</b>'''
            elif coordenadas == 4:
                txt = '''<b>[Xn]</b>, <b>[Yn]</b> e <b>h [Zn]m</b>'''
            elif coordenadas == 5:
                txt = '''<b>[Yn]</b>, <b>[Xn]</b> e <b>h [Zn]m</b>'''
            elif coordenadas == 6:
                txt = '''<b>[Xn]</b> e <b>[Yn]</b>'''
            elif coordenadas == 7:
                txt = '''<b>[Yn]</b> e <b>[Xn]</b>'''
            return txt.replace('[Yn]', str2HTML(y)).replace('[Xn]', str2HTML(x)).replace('[Zn]', str2HTML(z))
        
        # Modelo de descrição de confrontantes
        def DescrConfr (tipo, cns, mat, nome):
            if tipo == 0: # Apenas Nome
                return str2HTML(nome)
            elif tipo == 1 and mat: # Nome e Matrícula
                return str2HTML(nome + ' | Mat. ' + mat)
            elif tipo == 2 and mat and cns: # Nome, Matrícula e CNS
                return str2HTML(nome + ' | Mat. ' + mat + ' | CNS: ' + cns)
            elif tipo == 3 and mat and cns: # CNS, Matrícula e Nome
                return str2HTML('CNS: ' + cns + ' | Mat. ' + mat + ' | ' + nome )
            else:
                return str2HTML(nome)

        
        texto_inicial = '''<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>'''+ str2HTML('Memorial descritivo') + '''</title>

<style>
body {
    font-family: Arial, Helvetica, sans-serif;
    font-size: 12pt;
    color: #000000;
    line-height: 1.5;
}

p {
    margin: 0 0 10pt 0;
}

.logo {
    text-align: center;
    margin-bottom: 18pt;
}

.titulo {
    text-align: center;
    font-weight: bold;
    text-decoration: underline;
    font-size: 12pt;
    margin-bottom: 18pt;
}

.info {
    width: 100%;
    border-collapse: collapse;
    margin-bottom: 18pt;
}

.info td {
    padding: 3pt 8pt;
    vertical-align: top;
}

.descricao {
    text-align: justify;
    text-justify: inter-word;
    line-height: 1.5;
}

.data {
    text-align: right;
    margin-top: 18pt;
    margin-bottom: 36pt;
}

.assinatura {
    text-align: center;
    margin-top: 28pt;
    line-height: 1.3;
}
</style>
</head>

<body>

<div class="logo">
    <a target="_blank" rel="noopener noreferrer" href="https://geoone.com.br/">
        <img height="70" src="'''+ os.path.join(os.path.dirname(os.path.dirname(__file__)), 'images/GeoOne.png') +'''">
    </a><br>
    <em>'''+ str2HTML('Mapeamento automatizado, fácil e direto ao ponto é na GeoOne!') + '''</em>
</div>

<p class="titulo">'''+ str2HTML(self.tr('MEMORIAL DESCRITIVO')) + '''</p>

<table class="info">
<tbody>
<tr>
<td><strong>'''+ str2HTML(self.tr('Imóvel')) + ''':</strong> [IMOVEL]</td>
<td><strong>''' + str2HTML(self.tr('Código INCRA/SNCR')) + ''':</strong> [REGISTRO]</td>
</tr>

<tr>
<td colspan="2"><strong>''' + str2HTML(self.tr('Proprietário(a)')) + ''':</strong> [PROPRIETARIO]</td>
</tr>

<tr>
<td><strong>''' + str2HTML(self.tr('Município')) + ''':</strong> [MUNICIPIO]</td>
<td><strong>''' + str2HTML(self.tr('Estado')) + ''':</strong> [UF]</td>
</tr>

<tr>
<td colspan="2"><strong>''' + str2HTML(self.tr('Matrícula/Transcrição')) + ''':</strong> [MATRICULAS]</td>
</tr>

<tr>
<td><strong>''' + str2HTML(self.tr('Área (ha)')) + ''':</strong> [AREA]</td>
<td><strong>''' + str2HTML(self.tr('Perímetro')) + ''' (m):</strong> [PERIMETRO]</td>
</tr>

<tr>
<td colspan="2"><strong>''' + str2HTML(self.tr('Sistema de Referência de Coordenadas')) + ''':</strong> [SRC]</td>
</tr>
</tbody>
</table>

<p class="descricao">'''+ str2HTML(self.tr('Inicia-se a descrição deste perímetro n'))
        


        texto_var1 = (
            str2HTML(self.tr('o vértice ')) +
            '''<strong>[Vn]</strong>, ''' +
            str2HTML(self.tr('de coordenadas ')) +
            '''[Coordn], ''' +
            str2HTML(self.tr('deste, segue confrontando com [Confront_k], com os seguintes azimutes e distâncias: [Az_n] e [Dist_n]m até '))
        )

        texto_var2 = (
            str2HTML(self.tr('o vértice ')) +
            '''<strong>[Vn]</strong>, ''' +
            str2HTML(self.tr('de coordenadas ')) +
            '''[Coordn]; ''' +
            str2HTML(self.tr('[Az_n] e [Dist_n]m até '))
        )

        texto_calculo = self.tr(
            '. Os azimutes foram calculados pela fórmula do Problema Geodésico Inverso segundo Puissant. '
            'As distâncias, área e perímetro foram calculados no Sistema Geodésico Local (SGL) '
            'com origem na média das coordenadas cartesianas geocêntricas do imóvel.'
        )

        texto_final = (
            str2HTML(self.tr('o vértice ')) +
            '''<strong>[P-01]</strong>, ''' +
            str2HTML(self.tr('de coordenadas')) +
            ''' [Coord1], ''' +
            str2HTML(self.tr('ponto inicial da descrição deste perímetro. Todas as coordenadas aqui descritas estão georreferenciadas ao Sistema Geodésico de Referência (SGR)')) +
            ''' <strong>[GRS]</strong>''' +
            str2HTML(texto_calculo) +
            '''
        </p>

        <p class="data">[LOCAL], [DATA].</p>

        <div class="assinatura">
        <p>___________________________________________</p>
        <p>[OWNER]</p>
        <p>''' + str2HTML(self.tr('PROPRIETÁRIO DO IMÓVEL')) + '''</p>
        </div>

        <div class="assinatura">
        <p>___________________________________________</p>
        <p>[RESP_TEC]</p>
        <p>[CREA]</p>
        <p>''' + str2HTML(self.tr('RESPONSÁVEL TÉCNICO')) + '''</p>
        </div>

        </body>
        </html>
        '''
        )


        # Inserindo dados iniciais do levantamento
        proprietario = dic['Proprietário(a):'] if dic['Proprietário(a):'] else dic['Proprietário:']
        matricula = dic['Matrícula do imóvel:'] if dic['Matrícula do imóvel:'] else dic['Transcrição do imóvel:']
        itens = {'[IMOVEL]': str2HTML(dic['Denominação:']),
                '[PROPRIETARIO]': str2HTML(proprietario),
                '[MATRICULAS]': str2HTML(str(matricula) + ' | CNS: ' + dic['Cartório (CNS):']) if matricula else '-',
                '[AREA]': str2HTML(dic['Área (Sistema Geodésico Local)']),
                '[SRC]': str2HTML('SIRGAS2000'),
                '[REGISTRO]': str2HTML(dic['Código INCRA/SNCR:']),
                '[MUNICIPIO]': str2HTML(dic['Município/UF:'].split('-')[0]),
                '[UF]': str2HTML(dic['Município/UF:'].split('-')[-1]),
                '[PERIMETRO]': str2HTML(dic['Perímetro (m)']),
                    }

        for item in itens:
                texto_inicial = texto_inicial.replace(item, itens[item])

        LINHAS = texto_inicial
        mudou = True
        for k,codigo in enumerate(lista_cod_fat):
            if mudou:
                linha0 = texto_var1
                itens =    {'[Vn]': str2HTML(codigo),
                            '[Coordn]': CoordN(dic_cod[codigo]['lon'], dic_cod[codigo]['lat'], dic_cod[codigo]['h']),
                            '[Az_n]': str2HTML(dic_cod[codigo]['az']),
                            '[Dist_n]': str2HTML(dic_cod[codigo]['dist']),
                            '[Confront_k]': DescrConfr (tipoDescrConfront, dic_cod[codigo]['cns'], dic_cod[codigo]['matr'], dic_cod[codigo]['confr'])
                            }
                for item in itens:
                    linha0 = linha0.replace(item, itens[item])
                LINHAS += linha0
                #LIN0 = ''
                if dic_cod[codigo]['texto_confr']  == dic_cod[lista_cod_fat[0 if k+1 == len(lista_cod_fat) else k+1]]['texto_confr']:
                    mudou = False
            else:
                linha1 = texto_var2
                itens = {'[Vn]': str2HTML(codigo),
                        '[Coordn]': CoordN(dic_cod[codigo]['lon'], dic_cod[codigo]['lat'], dic_cod[codigo]['h']),
                        '[Az_n]': str2HTML(dic_cod[codigo]['az']),
                        '[Dist_n]': str2HTML(dic_cod[codigo]['dist'])
                        }
                for item in itens:
                    linha1 = linha1.replace(item, itens[item])
                LINHAS += linha1
                #LIN0 += linha1
                if dic_cod[codigo]['texto_confr']  != dic_cod[lista_cod_fat[0 if k+1 == len(lista_cod_fat) else k+1]]['texto_confr']:
                    mudou = True


        # Data do documento
        meses = {1: 'janeiro', 2:'fevereiro', 3: 'março', 4:'abril', 5:'maio', 6:'junho', 7:'julho', 8:'agosto', 9:'setembro', 10:'outubro', 11:'novembro', 12:'dezembro'}
        
        # Data da certificação
        try:
            dataAss = datetime.strptime(dic['Data Certificação:'], '%d/%m/%Y %H:%M')
        except:
            try:
                dataAss = datetime.strptime(dic['Data Certificação:'], '%d/%m/%y %H:%M')
            except:
                dataAss = None
        if dataAss:
            data_formatada = f"{dataAss.day:02d} de {meses[dataAss.month]} de {dataAss.year}"
        else:
            try:
                dataAss = datetime.strptime(dic['Data da Geração:'], '%d/%m/%Y %H:%M')
            except:
                try:
                    dataAss = datetime.strptime(dic['Data da Geração:'], '%d/%m/%y %H:%M')
                except:
                    dataAss = None
            if dataAss:
                data_formatada = f"{dataAss.day:02d} de {meses[dataAss.month]} de {dataAss.year}"
            else:
                dataAss = datetime.now().date()
                data_formatada = f"{dataAss.day:02d} de {meses[dataAss.month]} de {dataAss.year}"

        # Inserindo dados finais
        codigo = lista_cod_fat[0]
        itens = {   '[P-01]': str2HTML(codigo),
                    '[Coord1]': CoordN(dic_cod[codigo]['lon'], dic_cod[codigo]['lat'], dic_cod[codigo]['h']),
                    '[GRS]': 'SIRGAS 2000',
                    '[OWNER]': str2HTML(proprietario),
                    '[RESP_TEC]': str2HTML(dic['Responsável Técnico(a):'] if dic['Responsável Técnico(a):'] else dic['Responsável Técnico:']),
                    '[CREA]': str2HTML(dic['Formação:'] + ' | ' + dic['Conselho Profissional:']  + ' | ' + dic['Documento de RT:']),
                    '[LOCAL]': str2HTML(dic['Município/UF:']),
                    '[DATA]': str2HTML(data_formatada)
                    }

        for item in itens:
                texto_final = texto_final.replace(item, itens[item])
        LINHAS += texto_final
        output = self.parameterAsFileOutput(parameters, self.HTML, context)
        arq = open(output, 'w')
        arq.write(LINHAS)
        arq.close()

        
        # Preenchendo Memorial Sintético Tabular
        template = '''<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
  <meta charset="UTF-8">
  <title>Memorial Descritivo</title>
  <style>
body {
font-family: Arial, Helvetica, sans-serif;
font-size: 11px;
margin: 0;
padding: 10px;
}
table {
width: 100%;
border-collapse: collapse;
font-size: 11px;
text-align: center;
}
th, td {
border: 1px solid #000;
padding: 6px 4px;
vertical-align: middle;
}
thead th {
background-color: #f2f2f2;
font-weight: bold;
}
.titulo {
font-size: 14px;
font-weight: bold;
text-transform: uppercase;
background-color: #e6e6e6;
}
  </style>
</head>
<body>
<table>
  <thead>
  <tr>
    <th colspan="8" class="titulo">
DESCRI&Ccedil;&Atilde;O DA PARCELA
    </th>
  </tr>
  <tr>
    <th colspan="4">V&Eacute;RTICE</th>
    <th colspan="4">SEGMENTO VANTE</th>
  </tr>
  <tr>
    <th>C&oacute;digo</th>
    <th>Longitude</th>
    <th>Latitude</th>
    <th>Altitude (m)</th>
    <th>C&oacute;digo</th>
    <th>Azimute</th>
    <th>Dist. (m)</th>
    <th>Confronta&ccedil;&otilde;es</th>
  </tr>
  </thead>
  <tbody>
    [LINHAS]
  </tbody>
</table>
</body>
</html>
'''     
        template_linhas = '''<tr>
      <td>[C1]</td>
      <td>[LON]</td>
      <td>[LAT]</td>
      <td>[H]</td>
      <td>[C2]</td>
      <td>[AZ]</td>
      <td>[D]</td>
      <td>[CONFR]</td>
    </tr>
    '''

        linhas = ''
        for codigo in lista_cod_fat:
            linha = template_linhas
            itens = {'[C1]': str2HTML(codigo),
                     '[LON]': str2HTML(dic_cod[codigo]['lon']), 
                     '[LAT]': str2HTML(dic_cod[codigo]['lat']), 
                     '[H]': str2HTML(dic_cod[codigo]['h']), 
                     '[C2]': str2HTML(dic_cod[codigo]['vante']),
                     '[AZ]': str2HTML(dic_cod[codigo]['az']), 
                     '[D]': str2HTML(dic_cod[codigo]['dist']), 
                     '[CONFR]': str2HTML(dic_cod[codigo]['texto_confr']), 
                     }
            for item in itens:
                linha = linha.replace(item, itens[item])
            linhas += linha
        
        tabela_final = template.replace('[LINHAS]', linhas)
        output2 = self.parameterAsFileOutput(parameters, self.HTML2, context)
        arq = open(output2, 'w')
        arq.write(tabela_final)
        arq.close()


        return {self.HTML: output,
                self.HTML2: output2}
