import gradio as gr
import diff
import os
from PIL import Image
import uuid
import random
import bg
from rembg import remove as rm
import datetime 
from huggingface_hub import (HfApi,file_exists)
import uuid
import json
import requests
uid=uuid.uuid4()
proc1=diff
proc2=diff 
this_url='https://omnibus-game-test.hf.space/'
save_data='https://huggingface.co/datasets/Omnibus/game-data-1/raw/main/'
token_self = os.environ['HF_TOKEN']
api=HfApi(token=token_self)

sky = "https://huggingface.co/spaces/Omnibus/game-test/resolve/main/assets/sky.png"
star = 'https://huggingface.co/spaces/Omnibus/game-test/resolve/main/assets/star.png'
bomb = 'https://huggingface.co/spaces/Omnibus/game-test/resolve/main/assets/bomb.png'
platform = 'https://huggingface.co/spaces/Omnibus/game-test/resolve/main/assets/platform.png'
dude = 'https://huggingface.co/spaces/Omnibus/game-test/resolve/main/assets/dude.png'

get_window_url_params = """
    function(text_input, url_params) {
        console.log(text_input, url_params);
        const params = new URLSearchParams(window.location.search);
        url_params = Object.fromEntries(params);
        return [text_input, url_params];
        }
    """     
def game_fn(sky=sky,star=star,bomb=bomb,platform=platform,dude=dude):
    html_mod=f"""
        <div id="my_game" style="height:600px;width:100%">
            <iframe
            id="myIframe"
            src="https://omnibus-game-test.hf.space/file=game.html?sky={sky}&platform={platform}&star={star}&bomb={bomb}&dude={dude}"        
        	frameborder="0"
        	width="100%"
            height="100%"
            ></iframe>
        </div>"""
    return gr.HTML.update(f'{html_mod}')

def update_game(inp):
    return game_fn(sky=sky)

def sky_fn(inp):
    uid=uuid.uuid4()
    rand = random.randint(1,200)
    for i in range(rand):
        inp+=" "
    #uid=uuid.uuid4()
    output=proc1.send_it(inp,5,1)
    print(output)
    outp=Image.open(output[0])
    width, height = outp.size
    rat = width/height
    if width > height:
        outrs = outp.resize((600*rat,600))
    elif width < height:
        outrs = outp.resize((800,800*rat))     
    else:
        outrs = outp.resize((800,536))
    outrs.save(f"{uid}_sky.png")
    out = os.path.abspath(f"{uid}_sky.png")
    #out = os.path.abspath(outp)
    out_url = f'https://omnibus-game-test.hf.space/file={out}'    
    return outp,out_url

def star_fn(inp):
    uid=uuid.uuid4()
    rand = random.randint(1,200)
    for i in range(rand):
        inp+=" "
    #uid=uuid.uuid4()
    output=proc2.send_it(inp,5,1)
    outp=Image.open(output[0])
    out=rm(outp)
    outrs = out.resize((36,36))
    outrs.save(f"{uid}_star.png")
    out_file = os.path.abspath(f"{uid}_star.png")
    out_url = f'https://omnibus-game-test.hf.space/file={out_file}'    
    return out,out_url

def enemy_fn(inp):
    uid=uuid.uuid4()
    rand = random.randint(1,200)
    for i in range(rand):
        inp+=" "
    #uid=uuid.uuid4()
    output=proc2.send_it(inp,5,1)
    outp=Image.open(output[0])
    out=rm(outp)
    outrs = out.resize((24,24))
    outrs.save(f"{uid}_enemy.png")
    out_file = os.path.abspath(f"{uid}_enemy.png")
    out_url = f'https://omnibus-game-test.hf.space/file={out_file}'    
    return out,out_url

def save_game(name,score,sky_im,star_im,enemy_im):
    sky_im=sky_im.split("app/",1)[1]
    star_im=star_im.split("app/",1)[1]
    #sky_im=sky_im.split("app/",1)[1]
    print(star_im)
    user_repo=save_data.split('datasets/',1)[1].split('/raw',1)[0]
    timestamp=str(datetime.datetime.now())
    timename=timestamp.replace(" ","--").replace(":","-").replace(".","-")    
    if name != "":
        if file_exists(f"{user_repo}", f"games/{name}.omnigame",repo_type="dataset"):
            return "Game Saved with this Name.  Choose a different Name."
        else:
            game=name
    else:
        game=timename
    
    #out_lod=[]
    try:
        r = requests.get(f'{save_data}game_data.json') 
        lod = json.loads(r.text)
        #out_lod.append(lod)
    except:
        lod=[]
        pass
    try: 
        api.upload_file(
        path_or_fileobj=sky_im,
        path_in_repo=f"{save_data.split('main/',1)[1]}/images/background/{game}-background_img.png",
        repo_id=save_data.split('datasets/',1)[1].split('/raw',1)[0],
        token=token_self,
        repo_type="dataset",
        )
    except Exception as e:
        print (e)
        pass 
    try: 
        api.upload_file(
        path_or_fileobj=star_im,
        path_in_repo=f"{save_data.split('main/',1)[1]}/images/star/{game}-star_img.png",
        repo_id=save_data.split('datasets/',1)[1].split('/raw',1)[0],
        token=token_self,
        repo_type="dataset",
        )
    except Exception as e:
        print (e)
        pass  
    try: 
        api.upload_file(
        path_or_fileobj=enemy_im.split("app/",1)[1],
        path_in_repo=f"{save_data.split('main/',1)[1]}/images/enemy/{game}-enemy_img.png",
        repo_id=save_data.split('datasets/',1)[1].split('/raw',1)[0],
        token=token_self,
        repo_type="dataset",
        )
    except Exception as e:
        print (e)
        pass  
    try: 
        api.upload_file(
        path_or_fileobj="assets/platform.png",
        path_in_repo=f"{save_data.split('main/',1)[1]}/images/platform/{game}-platform_img.png",
        repo_id=save_data.split('datasets/',1)[1].split('/raw',1)[0],
        token=token_self,
        repo_type="dataset",
        )
    except Exception as e:
        print (e)
        pass  
    try: 
        api.upload_file(
        path_or_fileobj="assets/dude.png",
        path_in_repo=f"{save_data.split('main/',1)[1]}/images/dude/{game}-dude_img.png",
        repo_id=save_data.split('datasets/',1)[1].split('/raw',1)[0],
        token=token_self,
        repo_type="dataset",
        )
    except Exception as e:
        print (e)
        pass          
    block = {'index': len(lod) + 1,
            'timestamp': timestamp,
            'game_name': game,
            'score': score, 
            'background_url': f'https://huggingface.co/datasets/{user_repo}/resolve/main/images/background/{game}-background_img.png',
            'star_url': f'https://huggingface.co/datasets/{user_repo}/resolve/main/images/star/{game}-star_img.png',
            'enemy_url': f'https://huggingface.co/datasets/{user_repo}/resolve/main/images/enemy/{game}-enemy_img.png',
            'platform_url': f'https://huggingface.co/datasets/{user_repo}/resolve/main/images/platform/{game}-platform_img.png',
            'dude_url': f'https://huggingface.co/datasets/{user_repo}/resolve/main/images/dude/{game}-dude_img.png',
            }
    print(block)
    lod.append(block)    
    
    json_object = json.dumps(lod, indent=4)
    with open("tmp1.json", "w") as outfile:
        outfile.write(json_object)
    try: 
        api.upload_file(
        path_or_fileobj="tmp1.json",
        path_in_repo=f"{save_data.split('main/',1)[1]}/game_data.json",
        repo_id=save_data.split('datasets/',1)[1].split('/raw',1)[0],
        token=token_self,
        repo_type="dataset",
        )
        os.remove("tmp1.json")
        print("success")
    except Exception as e:
        print (e)
        return f'Error Saving Game: {e}'
    game_box=[]
    block2 = {'game_name': game,
            'score':score,
            'timestamp': timestamp,
            'background_url': f'https://huggingface.co/datasets/{user_repo}/resolve/main/images/background/{game}-background_img.png',
            'star_url': f'https://huggingface.co/datasets/{user_repo}/resolve/main/images/star/{game}-star_img.png',
            'enemy_url': f'https://huggingface.co/datasets/{user_repo}/resolve/main/images/enemy/{game}-enemy_img.png',
            'platform_url': f'https://huggingface.co/datasets/{user_repo}/resolve/main/images/platform/{game}-platform_img.png',
            'dude_url': f'https://huggingface.co/datasets/{user_repo}/resolve/main/images/dude/{game}-dude_img.png',
            }
    print(block)
    game_box.append(block2)    
    
    json_object = json.dumps(game_box, indent=4)
    with open("tmp2.json", "w") as outfile:
        outfile.write(json_object)
    try: 
        api.upload_file(
        path_or_fileobj="tmp2.json",
        path_in_repo=f"{save_data.split('main/',1)[1]}/games/{game}.omnigame",
        repo_id=save_data.split('datasets/',1)[1].split('/raw',1)[0],
        token=token_self,
        repo_type="dataset",
        )
        os.remove("tmp2.json")
        print("success")
        game_url=f'{this_url}?game={game}'
    except Exception as e:
        print (e)
        return f'Error Saving Game: {e}'
    return f"Game Saved<br>URL: <a href={game_url}>{game_url}</a>"
def predict(text, url_params):
    load_game=url_params.get('game')
    print (f'load_game::{load_game}')
    if load_game != None:
        try:
            r = requests.get(f'{save_data}games/{load_game}.omnigame') 
            lod = json.loads(r.text)
            game_html=game_fn(lod[0]['background_url'],lod[0]['star_url'],lod[0]['enemy_url'])
            #out_lod.append(lod)
            print (lod)
            print (game_html)
            return "" + text + "",game_html
        except Exception as e:
            print(f"cannot load game.  Error::{e}")
            pass
        
    else:
       pass
    return ["" + text + "", ""]

def get_high_score():
    try:
        r = requests.get(f'{save_data}game_data.json') 
        lod = json.loads(r.text)
        high_score=[0,0,0]
        sort_score=[0,0,0]
        #print(sort_score)
        for ea in lod:
            try:
                if ea['score'] != "":
                    if int(ea['score']) >= int(sort_score[0]):
                        sort_score[2]=sort_score[1]
                        high_score[2]=high_score[1]
                        sort_score[1]=sort_score[0]
                        high_score[1]=high_score[0]
                        sort_score[0]=ea['score']
                        high_score[0]=(f"{ea['score']}<br>{ea['game_name']}<br><br>")
                        pass
                    elif int(ea['score']) >= int(sort_score[1]):
                        sort_score[2]=sort_score[1]
                        high_score[2]=high_score[1]
                        sort_score[1]=ea['score']
                        high_score[1]=(f"{ea['score']}<br>{ea['game_name']}<br><br>")
                        pass
                    elif int(ea['score']) >= int(sort_score[2]):
                        sort_score[2]=ea['score']
                        high_score[2]=(f"{ea['score']}<br>{ea['game_name']}<br><br>")
                        pass
            except Exception as e:
                print(e)
                pass
        return f"<h3><u>High Score</u></h3><br>{high_score[0]}<br>{high_score[1]}<br>{high_score[2]}<br>"
    except Exception as e:
        return e    


score_js="""

function(text_input) {
    console.log(text_input);
    const iframe = document.getElementById("myIframe").contentWindow.document.getElementById('my_score').innerHTML;
    console.log(iframe);
    return [iframe];
}
"""

with gr.Blocks() as app:
    with gr.Row():
        with gr.Column():
            prompt_sky=gr.Textbox(label="Background",value="beautiful landscape, real, 8k")
            btn_sky=gr.Button("Make")
            out_im_sky=gr.Image(type='filepath')
            out_sky_url=gr.Textbox(visible=True)
        with gr.Column():
            prompt_star=gr.Textbox(label="Star",value="Colorful Star, blank background")
            btn_star=gr.Button("Make")
            out_im_star=gr.Image(type='filepath')
            out_star_url=gr.Textbox(visible=True)
        with gr.Column():
            prompt_enemy=gr.Textbox(label="Enemy",value="Ball on fire, blank background")
            btn_enemy=gr.Button("Make")
            out_im_enemy=gr.Image(type='filepath')
            out_enemy_url=gr.Textbox(visible=True)
        gr.Column()
        gr.Column()
        
    with gr.Row():
        update_game=gr.Button("Load Game")
        #start_prompt=gr.Textbox(value="beautiful landscape, real, 8k",visible=False)
    
    with gr.Row():
        with gr.Column(scale=3):
            html_game = gr.HTML()
        with gr.Column(scale=1):
            score_html =gr.HTML()        
    with gr.Row():
        game_name=gr.Textbox(label="Name for Game (optional)")
        save_btn=gr.Button("Save")
        message=gr.HTML()
    with gr.Row(visible=False):
        get_score=gr.Button("Get Score")
        score=gr.Textbox()
        #url_params=gr.Textbox()
    with gr.Row(visible=False):
        text_input=gr.Textbox()
        url_params = gr.JSON({}, visible=True, label="")
        acc=gr.Textbox()

        get_high_score_btn=gr.Button()
    def return_score(text):
        return text

    get_high_score_btn.click(get_high_score,None,score_html)    
    get_score.click(return_score,score,[score],_js=score_js)
    save_btn.click(return_score,score,[score],_js=score_js).then(save_game,[game_name,score,out_sky_url,out_star_url,out_enemy_url],message)
    update_game.click(game_fn,[out_sky_url,out_star_url,out_enemy_url],html_game).then(get_high_score,None,score_html)
    btn_sky.click(sky_fn,prompt_sky,[out_im_sky,out_sky_url])
    btn_star.click(star_fn,prompt_star,[out_im_star,out_star_url])
    btn_enemy.click(enemy_fn,prompt_enemy,[out_im_enemy,out_enemy_url])
    app.load(predict,[text_input,url_params],[text_input,html_game], _js=get_window_url_params) 

    #app.load(sky_fn,prompt_sky,[out_im_sky,out_sky_url]).then(game_fn,[out_sky_url],html_game)
app.queue(concurrency_count=10).launch()