#!/usr/bin/env python
import time
import random
import os
import yaml
import json
import subprocess




# Códigos de escape ANSI para cores
RESET = "\033[0m"
RED = "\033[91m"
GREEN = "\033[92m"
YELLOW = "\033[93m"
BLUE = "\033[94m"





def main():

    # Configurações iniciais para gerar o ARK
    config_geral = {

        "prefixo": "eM", # Você pode escolher o melhor para você ou deixar uma string vazia se não quiser usar prefixo
        "qtde_digitos_ark_nivel_1": 3, # Quantidade de dígitos sem contar o prefixo. Na Editora Moan estamos usando 3, mas você pode mudar de acordo com suas necessidades
        "qtde_digitos_ark_nivel_2": 2, # Quantidade de dígitos para um ARK filho. Na Editora Moan estamos usando 2, mas você pode mudar de acordo com suas necessidades
        "qtde_digitos_ark_nivel_3": 2, # Quantidade de dígitos para um ARK de variação. Na Editora Moan estamos usando 2, mas você pode mudar de acordo com suas necessidades
        "naan": "68745", # NAAN da Editora Moan na Ark Alliance
        "simbolos": "23456789bBdDfFgGhHjJmMnNpPqQrRtT", # Símbolos permitidos na geração do ark. Sinta-se a vontade, se quiser mudar.
        "pasta_yaml": "yaml", # Nome da pasta em que o programa verificará se já existe o ARK gerado. Nessa pasta, são armazenados os metadados em yaml do ARK gerado
        "pasta_json": "json", # Nessa pasta, são armazenados os metadados em json do ARK gerado
        "chave_primaria_yaml": "moan-dados" # Você pode escolher uma outra chave primária. Fazemos isso porque na Editora Moan usamos o Quarto Sistema de Publicações Científicas e os metadados sao armazenados em yaml. Mais especificamente no arquivo de configuração _quarto.yml. Como nesse arquivo existem diversas configurações, usamos a chave moan-dados para colocar os metadados que usaremos para gerar os identificadores ARK.

    }

    print(BLUE+"\n\n================================= \n\nBem-vindo ao script Moan ARK! \n\n=================================\n"+RESET)

    while True:

        func = input("\n+++++++++++++++++++++++++++++++++++++++++++\nInforme o número da função a ser executada.\n \n As Opções são:\n \n"+YELLOW+" 1 - Criar um identificador ARK\n 2 - Atualizar um identificador ARK\n 3 - Sair\n"+RESET+"+++++++++++++++++++++++++++++++++++++++++++\n➜ ")

        if func == "3":

            print(RED+"\nSaindo do programa...\n"+RESET)

            time.sleep(2)

            break  # Isso sairá do loop while e encerrará o programa.

        elif func not in ["1", "2", "3"]:

            print(RED+"\nOpção não reconhecida. Por favor, escolha 1, 2 ou 3.\n"+RESET)

            continue
  

        metadados = input("\nInsira o nome do arquivo de metadados com o caminho completo, incluindo a extensão (.yml). O arquivo deve ser um YAML e a chave inicial do arquivo .yml dve ser moan-dados.\n➜ ")

        if func == "1":

            nivel = input("\nQual o nível do identificador ARK deseja criar?\n \n"+YELLOW+" 1 - Nível Inicial \n 2 - Nível Secundário \n 3 - ARK de Variação\n"+RESET+"➜ ")

            if nivel == "1":

                criar_identificador_ARK(config_geral, metadados, nivel)


            elif nivel == "2" or nivel == "3":

                ark_pai = input("\nInsira o identificador ARK. Coloque o identificador ARK completo até onde você deseja criar um novo nível ou uma nova variação. Mas não coloque o rótulo ark: e nem o naan. Exemplo: ark:/68745/eM37b/pM.MG. Veja que o ARK inicial é eM37b, temos o filho pM e a variação MG. Vamos supor que queremos criar mais um filho de eM37b, então só colocaríamos eM37b. Agora, se a ideia é criar um filho para a variação MG do filho pM, colocaríamos eM37b/pM.MG. Lembre-se que os ARK filhos são partes da obra, por exemplo, fascículos de uma coleção; já, a variação ocorre quando temos formatos diferentes da mesma obra, como pdf, online, epub ou ainda com idiomas diferentes.\n➜ ")

                criar_identificador_ARK(config_geral, metadados, nivel, ark_pai)


            else:

                print(RED+"\nOpção não reconhecida. Por favor, escolha 1, 2 ou 3. \n"+RESET)

                continue

        elif func == "2":

            atualizar_identificador_ARK(config_geral, metadados)





def filtrar(ark):

    # essa função transforma o identificador ARK na forma em que os arquivos ARK são nomeados. Um ark pode ter ":" (dois pontos), "/" (barra) ou "." (ponto). Mas isso, em um nome de arquivo atrapalha a url. Assim, transformaremos : em _dp_, / em _b_ e . em _p_.

    ark = ark.replace("/", "_b_").replace(".", "_p_")

    ark = "ark_dp_" + ark

    return ark
    



def criar_identificador_ARK(config_geral, metadados, nivel, ark_pai=None):



    # pegando as configurações gerais
    prefixo = config_geral["prefixo"]

    naan = config_geral["naan"]

    simbolos = config_geral["simbolos"]

    pasta_yaml = config_geral["pasta_yaml"]

    pasta_json = config_geral["pasta_json"]

    chave_primaria_yaml = config_geral["chave_primaria_yaml"]





     
    

    print(BLUE+"\nCriando o identificador ARK...\n"+RESET)

    while True: 

        # criando o ARK de nível 1
        if nivel == "1":  

            ark = naan + "/" + prefixo

            qtde_digitos = config_geral["qtde_digitos_ark_nivel_1"]


        # criando o ARK de nível 2, o u qualquer nível conforme o ark_pai passado
        elif nivel == "2":

            ark = naan + "/" + ark_pai + "/"

            qtde_digitos = config_geral["qtde_digitos_ark_nivel_2"]



        # criando o ARK de variação
        elif nivel == "3":

            ark = naan + "/" + ark_pai + "."

            qtde_digitos = config_geral["qtde_digitos_ark_nivel_3"]




        for i in range(qtde_digitos):

            numero_sorteado = random.randint(0, 31)

            ark += simbolos[numero_sorteado]

            
        ark_filtrado = filtrar(ark)

        nome_arquivo_ark_yml = ark_filtrado + ".yml"
            
        caminho_completo_gravacao_yml = os.path.join(pasta_yaml, nome_arquivo_ark_yml)


        # Verificar se o arquivo já existe na pasta yaml. Se existir, gerar um novo identificador ARK. Agora, se não existir, pega o caminho do metadados e cria o arquivo, lançando a mensagem de ARK criado com sucesso...

        if os.path.exists(caminho_completo_gravacao_yml):

            print(RED+f"\nO identificador 'ark:{ark}' já existe. \nVamos gerar outro. Aguarde...\n"+RESET)

            continue

        else:

            # Verifique se o arquivo YAML com os metadados para gerar o ARK existe. Aqui na Editora Moan, usamos o arquivo _quarto.yml
            if not os.path.exists(metadados):

                print(RED+"\nArquivo YAML não encontrado.\n"+RESET)
                    
                time.sleep(2)

                break


            # Mensagem de ARK criado com sucesso. Iniciando a gravação dos metadados...
            print(GREEN+f"\nO identificador 'ark:{ark}' foi criado com sucesso!\n\nAgora vamos gravar os metadados e gerar os arquivos nas pastas correspondentes... Aguarde...\n"+RESET)

            time.sleep(1)



            # Carregue o arquivo YAML
            with open(metadados, 'r', encoding='utf-8') as arquivo_yaml:

                dados_yaml = yaml.load(arquivo_yaml, Loader=yaml.FullLoader)



                
            # Verifique se 'chave_primaria_yaml' (no caso da Editora Moan, ela é moan-dados) existe e 'ark' não existe dentro dele
            if chave_primaria_yaml in dados_yaml and 'ark' not in dados_yaml[chave_primaria_yaml]:


                # As chaves 'título', 'formato' e 'autor' são obrigatorias para geração de identificador ARK
                if 'título' in dados_yaml[chave_primaria_yaml] and 'formato' in dados_yaml[chave_primaria_yaml] and 'autor' in dados_yaml[chave_primaria_yaml]:


                    # Adicione 'ark' ao 'chave_primaria_yaml' com o valor de ark. Quero que o ark seja a primeira chave, por isso coloquei da forma que está abaixo
                    dados_yaml[chave_primaria_yaml] = {'ark' : ark, **dados_yaml[chave_primaria_yaml]}




                    # Salve os dados atualizados no arquivo original
                    with open(metadados, 'w', encoding='utf-8') as arquivo_yaml:

                        yaml.dump(dados_yaml, arquivo_yaml, default_style='', sort_keys=False, allow_unicode=True)


                    # Crie um novo dicionário contendo apenas os dados da chave_primaria_yaml 'moan-dados'
                    metadados_yaml_a_gravar = dados_yaml[chave_primaria_yaml]



                    # Salve os dados atualizados em um novo arquivo YAML
                    with open(caminho_completo_gravacao_yml, 'w', encoding='utf-8') as novo_arquivo_yaml:

                        yaml.dump(metadados_yaml_a_gravar, novo_arquivo_yaml, default_style='', sort_keys=False, allow_unicode=True, default_flow_style=False)



                    # Resumo dos metadados em YAML
                    metadados_resumo_yaml_a_gravar = {dados_yaml[chave_primaria_yaml]['ark']:

                                                            {

                                                                'título': dados_yaml[chave_primaria_yaml]['título'],
                                                                'formato': dados_yaml[chave_primaria_yaml]['formato'],
                                                                'autor': dados_yaml[chave_primaria_yaml]['autor'],
                                                                'ark-filtrado': ark_filtrado,

                                                            }

                                                        }  
                        

                    #pega o diretório atual
                    diretorio_atual = os.getcwd()

                    caminho_completo_yaml_existente = os.path.join(diretorio_atual, "ark_lista.yml")


                    # Abre o arquivo YAML existente em modo de leitura
                    with open(caminho_completo_yaml_existente, 'r', encoding='utf-8') as arquivo_yaml_existente:

                        # Carrega o conteúdo do arquivo YAML existente
                        dados_yaml_existente = yaml.load(arquivo_yaml_existente, Loader=yaml.FullLoader)



                    # Atualiza com os dados novos
                    dados_yaml_existente.update(metadados_resumo_yaml_a_gravar)


                    # Salve o resumo dos metadados em um novo arquivo YAML
                    with open(caminho_completo_yaml_existente, 'w', encoding='utf-8') as arquivo_yaml_existente:

                        yaml.dump(dados_yaml_existente, arquivo_yaml_existente, default_style='', sort_keys=False, allow_unicode=True, default_flow_style=False)


                    output_yaml = '/media/rafael-tavares-juliani/Arq1/Repositorios/site-moan-quarto-config/site-livroonline/publicacoes.yml'

                    publicacao = "- title: " + dados_yaml[chave_primaria_yaml]['título'] + "\n" + \
                                "  subtitle: " + dados_yaml[chave_primaria_yaml]['ark'] + "\n" + \
                                "  author: " + dados_yaml[chave_primaria_yaml]['autor'] + "\n" + \
                                "  categories: [" + dados_yaml[chave_primaria_yaml]['formato'] + "]\n" + \
                                "  path: https://ark.livro.online/json/" + ark_filtrado + ".json\n"

                    # Leia todo o conteúdo atual do arquivo YAML
                    with open(output_yaml, 'r+', encoding='utf-8') as file:
                        # Leia o conteúdo existente e armazene em uma variável
                        conteudo_existente = file.read()
                        
                        # Volte para o início do arquivo
                        file.seek(0)
                        
                        # Adicione a nova publicacao no início do conteúdo existente
                        file.write(publicacao + conteudo_existente)




                    # Converta os dados para JSON
                    metadados_json_a_gravar = json.dumps(dados_yaml[chave_primaria_yaml], ensure_ascii=False, indent=2)



                    # Salve os dados JSON em um arquivo JSON
                    caminho_completo_gravacao_json = os.path.join(pasta_json, ark_filtrado + '.json')

                    with open(caminho_completo_gravacao_json, 'w', encoding='utf-8') as novo_arquivo_json:

                        novo_arquivo_json.write(metadados_json_a_gravar)






                    # Resumo dos metadados em JSON
                    metadados_resumo_json_a_gravar = {

                            dados_yaml[chave_primaria_yaml]['ark']: {

                                'título': dados_yaml[chave_primaria_yaml]['título'],
                                'formato': dados_yaml[chave_primaria_yaml]['formato'],
                                'autor': dados_yaml[chave_primaria_yaml]['autor'],
                                'ark-filtrado': ark_filtrado,

                            }
                    }


                    # Caminho completo para o arquivo JSON existente
                    caminho_completo_json_existente = os.path.join(diretorio_atual, "ark_lista.json")

                    # Abre o arquivo JSON existente em modo de leitura
                    with open(caminho_completo_json_existente, 'r', encoding='utf-8') as arquivo_json_existente:

                        # Carrega o conteúdo do arquivo JSON existente
                        dados_json_existente = json.load(arquivo_json_existente)

                    # Atualiza com os dados novos
                    dados_json_existente.update(metadados_resumo_json_a_gravar)

                    # Salve o resumo dos metadados em um novo arquivo JSON
                    with open(caminho_completo_json_existente, 'w', encoding='utf-8') as arquivo_json_existente:

                        json.dump(dados_json_existente, arquivo_json_existente, ensure_ascii=False, indent=2)






                    print(BLUE+f"\n*********************\n*********************\n\n"+GREEN+"O identificador "+YELLOW+f"'ark:{ark}'"+GREEN+" foi criado com sucesso e os seus "+YELLOW+"metadados foram gravados.\n\n"+BLUE+"*********************\n*********************\n"+RESET)

                    executar_script_atualizar_servidor()


                    time.sleep(2)

                    break


                else:

                    print(RED+f"\nAs chaves 'título', 'formato' e 'autor' são obrigatorias para geração de identificador ARK.\n"+RESET)

                    time.sleep(2)

                    break



                   


            else:

                # Ou a chave moan-dados não foi configurada no arquivo YAML com os metadados (o arquivo _quarto.yml, no caso da Editora Moan), ou então a chave ark já existe, o que indica que você deve usar a função de atualizar, e não gerar um novo ARK.

                print(RED+f"\nOu a chave chave_primaria_yaml, que está registrada como {chave_primaria_yaml} no dicionário Python config_geral no início da função main, não foi configurada no arquivo YAML com os metadados (o arquivo _quarto.yml, no caso da Editora Moan), ou então a chave ark já existe, o que indica que você deve usar a função de atualizar, e não gerar um novo ARK.\n"+RESET)

                time.sleep(2)

                break
           






def atualizar_identificador_ARK(config_geral, arquivo_atualizado):

    # pegando as configurações gerais
    pasta_yaml = config_geral["pasta_yaml"]

    pasta_json = config_geral["pasta_json"]

    chave_primaria_yaml = config_geral["chave_primaria_yaml"]


    if os.path.exists(arquivo_atualizado):

        print(BLUE+"\nAtualizando os metadados do identificador ARK...\n"+RESET)        


        # Carregue o arquivo YAML com os metadados atualizados
        with open(arquivo_atualizado, 'r', encoding='utf-8') as arquivo_yaml:

            dados_yaml = yaml.load(arquivo_yaml, Loader=yaml.FullLoader)

        ark_atualizado = dados_yaml[chave_primaria_yaml]['ark']

        ark_filtrado = ark_atualizado.replace("/", "_b_").replace(".", "_p_")

        ark_filtrado = "ark_dp_" + ark_filtrado

        arquivo_yaml_a_ser_atualizado = filtrar(ark_atualizado)+".yml"

        caminho_completo_atualizacao_yml = os.path.join(pasta_yaml, arquivo_yaml_a_ser_atualizado)

        arquivo_json_a_ser_atualizado = filtrar(ark_atualizado)+".json"

        caminho_completo_atualizacao_json = os.path.join(pasta_json, arquivo_json_a_ser_atualizado)




        if os.path.exists(caminho_completo_atualizacao_yml):           

            # Crie um novo dicionário contendo apenas os dados da chave_primaria_yaml 'moan-dados'
            metadados_yaml_a_atualizar = dados_yaml[chave_primaria_yaml]



            # Salve os dados atualizados em um novo arquivo YAML
            with open(caminho_completo_atualizacao_yml, 'w', encoding='utf-8') as novo_arquivo_yaml:

                yaml.dump(metadados_yaml_a_atualizar, novo_arquivo_yaml, default_style='', sort_keys=False, allow_unicode=True, default_flow_style=False)

            print(GREEN+"\nArquivo "+YELLOW+caminho_completo_atualizacao_yml+GREEN+" atualizado com sucesso.\n"+RESET)

        else:

            print(RED+"\nO arquivo "+YELLOW+caminho_completo_atualizacao_yml+RED+" não foi encontrado. Isso indica seu arquivo tem um identificador ARK, mas o mesmo não tem um arquivo de metadados YAML público.\n"+RESET)

            return


        # Carregue o arquivo YAML ark_lista
        with open("ark_lista.yml", 'r', encoding='utf-8') as arquivo_yaml:

            dados_yaml_lista = yaml.load(arquivo_yaml, Loader=yaml.FullLoader)


        metadados_resumo_yaml_atualizacao = {

            'título': dados_yaml[chave_primaria_yaml]['título'],
            'formato': dados_yaml[chave_primaria_yaml]['formato'],
            'autor': dados_yaml[chave_primaria_yaml]['autor'],
            'ark-filtrado': ark_filtrado,

        }

                                        

        dados_yaml_lista[ark_atualizado] = metadados_resumo_yaml_atualizacao

        with open("ark_lista.yml", 'w', encoding='utf-8') as atualizacao_arquivo_yaml:

            yaml.dump(dados_yaml_lista, atualizacao_arquivo_yaml, default_style='', sort_keys=False, allow_unicode=True, default_flow_style=False)


        print(GREEN+"\nArquivo "+YELLOW+"ark_lista.yml"+GREEN+" atualizado com sucesso.\n"+RESET)

        # Atualizar o ark no arquivo publicacoes.yml
        output_yaml = '/media/rafael-tavares-juliani/Arq1/Repositorios/site-moan-quarto-config/site-livroonline/publicacoes.yml'

        # Carrega o arquivo publicacoes.yml
        with open(output_yaml, 'r', encoding='utf-8') as file:
            publicacoes = yaml.load(file, Loader=yaml.FullLoader)

        publicacao = {

            'title': dados_yaml[chave_primaria_yaml]['título'],
            'subtitle': ark_atualizado,
            'categories': [dados_yaml[chave_primaria_yaml]['formato']],
            'author': dados_yaml[chave_primaria_yaml]['autor'],
            'path': "https://ark.livro.online/json/"+ark_filtrado+".json",
        }


        for item in publicacoes:
            if item['subtitle'] == ark_atualizado:
                item.update(publicacao)


        # Abre o arquivo publicacoes.yml com a codificação utf-8
        with open(output_yaml, 'w', encoding='utf-8') as file:
            # grava a atualização
             yaml.dump(publicacoes, file, encoding='utf-8', default_flow_style=False, sort_keys=False)




        if os.path.exists(caminho_completo_atualizacao_json):

            # Converta os dados para JSON
            metadados_json_atualizacao = json.dumps(dados_yaml[chave_primaria_yaml], ensure_ascii=False, indent=2)


            # Faz a Atualização do arquivo JSON
            with open(caminho_completo_atualizacao_json, 'w', encoding='utf-8') as novo_arquivo_json:

                novo_arquivo_json.write(metadados_json_atualizacao)


            print(GREEN+"\nArquivo "+YELLOW+caminho_completo_atualizacao_json+GREEN+" atualizado com sucesso.\n"+RESET)
            

            # Abre o ark_lista.json em modo de leitura
            with open("ark_lista.json", 'r', encoding='utf-8') as atualizacao_arquivo_json:

                ark_lista_json = json.load(atualizacao_arquivo_json)


            chave_atualizacao = dados_yaml[chave_primaria_yaml]['ark']


            # Resumo dos metadados em JSON
            ark_lista_json[chave_atualizacao].update( {

                    'título': dados_yaml[chave_primaria_yaml]['título'],
                    'formato': dados_yaml[chave_primaria_yaml]['formato'],
                    'autor': dados_yaml[chave_primaria_yaml]['autor'],
                    'ark-filtrado': ark_filtrado,

            })


            # Salve as atualizações de volta no arquivo JSON
            with open("ark_lista.json", 'w', encoding='utf-8') as atualizacao_arquivo_json:
    
                json.dump(ark_lista_json, atualizacao_arquivo_json, ensure_ascii=False, indent=2)


            print(GREEN+"\nArquivo "+YELLOW+"ark_lista.json"+GREEN+" atualizado com sucesso.\n"+RESET)

            executar_script_atualizar_servidor()




        else:

            print(RED+"\nO arquivo "+YELLOW+caminho_completo_atualizacao_json+RED+" não foi encontrado. Isso indica seu arquivo tem um identificador ARK, mas o mesmo não tem um arquivo de metadados JSON público.\n"+RESET)

            return


    else:

        print(RED+"\nO arquivo "+YELLOW+arquivo_atualizado+RED+" não foi encontrado.\n"+RESET)
        







# Função para executar o script atualizarServidor.py
def executar_script_atualizar_servidor():
    # Obtém o diretório atual
    diretorio_atual = os.path.dirname(os.path.abspath(__file__))

    # Concatena o nome do script ao diretório atual
    caminho_script = os.path.join(diretorio_atual, "atualizarServidor.py")

    try:
        # Executa o script atualizarServidor.py
        subprocess.run(["python", caminho_script], check=True)
        print("Script atualizarServidor.py executado com sucesso!")
    except subprocess.CalledProcessError as e:
        print(f"Ocorreu um erro ao executar o script atualizarServidor.py: {e}")








# Chama a função principal
if __name__ == "__main__":

    main()
