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

#os.makedirs('assets', exist_ok=True)
if not os.path.exists('icon.jpg'):
    os.system("wget -O icon.jpg https://i.pinimg.com/564x/64/49/88/644988c59447eb00286834c2e70fdd6b.jpg")
API_URL_DEV ="https://api-inference.huggingface.co/models/black-forest-labs/FLUX.1-dev"
API_URL = "https://api-inference.huggingface.co/models/black-forest-labs/FLUX.1-schnell"
timeout = 100

def query(prompt, is_negative=False, steps=30, cfg_scale=7, sampler="DPM++ 2M Karras", seed=-1, strength=0.7, huggingface_api_key=None):
    # Check if the request is an API call by checking for the presence of the huggingface_api_key
    is_api_call = huggingface_api_key is not None

    if is_api_call:
        
        # Use the environment variable for the API key in GUI mode
        API_TOKEN = os.getenv("HF_READ_TOKEN")
        headers = {"Authorization": f"Bearer {API_TOKEN}"}
        
    else:
        # Validate the API key if it's an API call
        if huggingface_api_key == "":
            raise gr.Error("API key is required for API calls.")
        
        headers = {"Authorization": f"Bearer {huggingface_api_key}"}
    
    if prompt == "" or prompt is None:
        return None

    key = random.randint(0, 999)

    prompt = GoogleTranslator(source='ru', target='en').translate(prompt)
    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}')

    # If seed is -1, generate a random seed and use it
    if seed == -1:
        seed = random.randint(1, 1000000000)

    payload = {
        "inputs": prompt,
        "is_negative": is_negative,
        "steps": steps,
        "cfg_scale": cfg_scale,
        "seed": seed,
        "strength": strength
    }

    response = requests.post(API_URL_DEV, 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})')

        # Save the image to a file and return the file path and seed
        output_path = f"./output_{key}.png"
        image.save(output_path)
        
        return output_path, seed
    except Exception as e:
        print(f"Error when trying to open the image: {e}")
        return None, None

css = """
#app-container {
    max-width: 600px;
    margin-left: auto;
    margin-right: auto;
}
#title-container {
    display: flex;
    align-items: center;
    justify-content: center;
}

#title-icon {
    width: 32px; /* Adjust the width of the icon as needed */
    height: auto;
    margin-right: 10px; /* Space between icon and title */
}

#title-text {
    font-size: 24px; /* Adjust font size as needed */
    font-weight: bold;
}
"""

with gr.Blocks(theme='Nymbo/Nymbo_Theme', css=css) as app:
    gr.HTML("""
        <center>
            <div id="title-container">
                <img id="title-icon" src="icon.jpg" alt="Icon">
                <h1 id="title-text">FLUX Capacitor</h1>
            </div>
        </center>
    """)

    with gr.Column(elem_id="app-container"):
        with gr.Row():
            with gr.Column(elem_id="prompt-container"):
                with gr.Row():
                    text_prompt = gr.Textbox(label="Prompt", placeholder="Enter a prompt here", lines=2, elem_id="prompt-text-input")
                with gr.Row():
                    with gr.Accordion("Advanced Settings", open=False):
                        negative_prompt = gr.Textbox(label="Negative Prompt", placeholder="What should not be in the image", 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="Sampling steps", value=35, minimum=1, maximum=100, step=1)
                        cfg = gr.Slider(label="CFG Scale", value=7, minimum=1, maximum=20, step=1)
                        method = gr.Radio(label="Sampling method", value="DPM++ 2M Karras", choices=["DPM++ 2M Karras", "DPM++ SDE Karras", "Euler", "Euler a", "Heun", "DDIM"])
                        strength = gr.Slider(label="Strength", value=0.7, minimum=0, maximum=1, step=0.001)
                        seed = gr.Slider(label="Seed", value=-1, minimum=-1, maximum=1000000000, step=1)
                        huggingface_api_key = gr.Textbox(label="Hugging Face API Key (required for API calls)", placeholder="Enter your Hugging Face API Key here", type="password", elem_id="api-key")

        with gr.Row():
            text_button = gr.Button("Run", variant='primary', elem_id="gen-button")
        with gr.Row():
            # Define two outputs: one for the image file path and one for the seed
            #image_path_output = gr.Textbox(label="Image File Path", elem_id="gallery")
            image_output = gr.Image(type="pil", label="Image Output", elem_id="gallery")
            seed_output = gr.Textbox(label="Seed Used", elem_id="seed-output")
        
        # Adjust the click function to include the API key as an input
        text_button.click(query, inputs=[text_prompt, negative_prompt, steps, cfg, method, seed, strength, huggingface_api_key], outputs=[image_output, seed_output])

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