import gradio as gr
import requests
import io
import random
import os
from PIL import Image
from deep_translator import GoogleTranslator

# Project by Nymbo

API_URL = "https://api-inference.huggingface.co/models/black-forest-labs/FLUX.1-dev"
API_TOKEN = os.getenv("HF_READ_TOKEN")
headers = {"Authorization": f"Bearer {API_TOKEN}"}
timeout = 100

def query(prompt, is_negative=False, steps=30, cfg_scale=7, strength=0.7):
    if not prompt:
        return None

    key = random.randint(0, 999)
    
    # Detectar el idioma del prompt y traducirlo al inglés
    translator = GoogleTranslator(target='en')
    try:
        prompt = translator.translate(prompt)
    except Exception as e:
        print(f"Error during translation: {e}")
        return None

    print(f'\033[1mGeneration {key} translation:\033[0m {prompt}')

    prompt = f"{prompt} | ultra detail, ultra elaboration, ultra quality, perfect."
    print(f'\033[1mGeneration {key}:\033[0m {prompt}')
    
    payload = {
        "inputs": prompt,
        "is_negative": is_negative,
        "steps": steps,
        "cfg_scale": cfg_scale,
        "strength": strength
    }

    response = requests.post(API_URL, headers=headers, json=payload, timeout=timeout)
    if response.status_code != 200:
        print(f"Error: Failed to get image. Response status: {response.status_code}")
        print(f"Response content: {response.text}")
        if response.status_code == 503:
            raise gr.Error(f"{response.status_code} : The model is being loaded")
        raise gr.Error(f"{response.status_code}")
    
    try:
        image_bytes = response.content
        image = Image.open(io.BytesIO(image_bytes))
        print(f'\033[1mGeneration {key} completed!\033[0m ({prompt})')
        return image
    except Exception as e:
        print(f"Error when trying to open the image: {e}")
        return None

def reset_prompt():
    default_text_prompt = ""  # Valor por defecto para el campo de texto
    default_negative_prompt = "(deformed, distorted, disfigured), poorly drawn, bad anatomy, wrong anatomy, extra limb, missing limb, floating limbs, (mutated hands and fingers), disconnected limbs, mutation, mutated, ugly, disgusting, blurry, amputation, misspellings, typos"  # Valor por defecto para el campo de texto negativo
    default_steps = 35  # Valor por defecto para el slider de pasos de muestreo
    default_cfg = 7  # Valor por defecto para el slider de nivel de detalle
    default_strength = 0.7  # Valor por defecto para el slider de fuerza de transformación
    
    return default_text_prompt, default_negative_prompt, default_steps, default_cfg, default_strength

css = """
#app-container {
    max-width: 100%;
    margin: 0 auto;
    padding: 20px;
}

input, textarea, select {
    background-color: #f5f5f5;
    color: #333333;
    border: 1px solid #cccccc;
    width: calc(100% - 40px);
    box-sizing: border-box;
    padding-right: 40px;
}

input[type="text"] {
    position: relative;
}

input[type="text"]::after {
    content: "✕";
    position: absolute;
    right: 10px;
    top: 50%;
    transform: translateY(-50%);
    cursor: pointer;
    color: #666;
}

button {
    background-color: #f5f5f5;
    color: #333333;
    border: 1px solid black;
    width: 100%;
    box-sizing: border-box;
    padding: 10px;
}

button.primary {
    background-color: green;
    color: black;
}

button.secondary {
    background-color: #f5f5f5;
    color: #333333;
}

button:hover {
    background-color: #e0e0e0;
}

h1, h2, h3, h4, h5, h6 {
    color: #333333;
}

@media (max-width: 768px) {
    .button-container {
        display: flex;
        flex-direction: column;
        align-items: center;
    }

    .button-container button {
        width: auto;
        margin-top: 10px;
    }
}

@media (min-width: 769px) {
    .button-container {
        display: flex;
        justify-content: flex-end;
    }

    .button-container button {
        width: auto;
    }
}
"""

examples = [
    "Minions con gafas atrapados en un bloque de hielo transparente, mostrando expresiones de sorpresa. Hielo escarchado y agrietado que refleja luz azul. Copos de nieve caen suavemente en un paisaje invernal.",
    "Un caballo marrón dorado trotando alegremente en realismo 8K contra un cielo vibrante con nubes multicolores en azul, rosa y naranja.",
    "Casco de Kylo Ren en forma de gato con texturas rugosas. Renderizado 3D ultra detallado con iluminación de borde y texturas hiperrealistas. Tonos pulidos según los colores de Kylo Ren, renderizado octano en 8K, fondo contrastado."
]

with gr.Blocks(css=css) as app:
    gr.HTML("""
    <center>
        <h1>Dream Generator with Flux</h1>
        <h2>Transforma tus sueños en imágenes vibrantes con un solo clic.</h2>
    </center>
    """)
    
    with gr.Row():
        with gr.Column(scale=1):
            text_prompt = gr.Textbox(
                label="¿Cuál fue tu sueño?", 
                placeholder="Describe lo que soñaste, no omitas ningún detalle.", 
                lines=2, 
                elem_id="prompt-text-input"
            )

            with gr.Accordion("Opciones Avanzadas", open=False):
                negative_prompt = gr.Textbox(
                    label="¿Qué elementos no deseas que se plasmen de tu sueño?", 
                    placeholder="Describe en detalle lo que quieres que aparezca.", 
                    value="(deformed, distorted, disfigured), poorly drawn, bad anatomy, wrong anatomy, extra limb, missing limb, floating limbs, (mutated hands and fingers), disconnected limbs, mutation, mutated, ugly, disgusting, blurry, amputation, misspellings, typos", 
                    lines=3, 
                    elem_id="negative-prompt-text-input"
                )
                steps = gr.Slider(
                    label="Profundidad del sueño (Pasos de muestreo)", 
                    value=35, 
                    minimum=1, 
                    maximum=100, 
                    step=1
                )
                cfg = gr.Slider(
                    label="Claridad del sueño (Nivel de detalle)", 
                    value=7, 
                    minimum=1, 
                    maximum=20, 
                    step=1
                )
                strength = gr.Slider(
                    label="Intensidad del sueño (Fuerza de transformación)", 
                    value=0.7, 
                    minimum=0, 
                    maximum=1, 
                    step=0.001
                )

            gr.Examples(examples=examples, inputs=text_prompt, label="Ejemplos de otros sueños")
            
            with gr.Row(elem_id="button-container"):
                generate_button = gr.Button("QUIERO VER MI SUEÑO", elem_id="generate-button", variant="primary")
                reset_button = gr.Button("REINICIAR MI SUEÑO", elem_id="reset-button", variant="secondary")
                
        with gr.Column(scale=1):
            image_output = gr.Image(type="pil", label="Image Output", elem_id="gallery")

    generate_button.click(query, inputs=[text_prompt, negative_prompt, steps, cfg, strength], outputs=image_output)
    reset_button.click(reset_prompt, outputs=[text_prompt, negative_prompt, steps, cfg, strength])

app.launch(show_api=False, share=False)