import gradio as gr
from huggingface_hub import create_repo, whoami, Repository
import subprocess
import os, shutil


def fork(source_repo, dst_repo, token, repo_type):
    # Creating repos has inconsistent API (https://github.com/huggingface/huggingface_hub/issues/47)
    repo_namespace, dst_id = dst_repo.split("/")
    username = whoami(token)
    org = None
    if repo_namespace != username:
        org = repo_namespace

    # Create the destination repo
    if repo_type in ["space", "dataset"]:
        # For some reason create_repo does not allow repo_type="model"..., even if documentation says
        # that's the default.
        create_repo(
            dst_id,
            token=token,
            organization=org,
            repo_type=repo_type,
            space_sdk="gradio",
        )
    else:
        create_repo(dst_id, token=token)

    # Clone source repo
    endpoint = "https://huggingface.co/"
    if repo_type in ["space", "dataset"]:
        endpoint += repo_type
    full_path = endpoint + "/" + source_repo
    local_dir = "hub/" + source_repo

    if repo_type in ["space", "dataset"]:
        # Same as above
        repo = Repository(
            local_dir=local_dir, clone_from=full_path, repo_type=repo_type
        )
    else:
        repo = Repository(local_dir=local_dir, clone_from=full_path)

    # Change remote origin
    command = f"git remote set-url origin https://user:{token}@huggingface.co/"
    if repo_type in ["space", "dataset"]:
        # Can we not have to add the s here? Why do we use singular and plural inconsistently?
        command += repo_type + "s/"

    command += dst_repo
    subprocess.run(
        command.split(),
        stderr=subprocess.PIPE,
        stdout=subprocess.PIPE,
        encoding="utf-8",
        check=True,
        cwd=local_dir,
    )

    subprocess.run(
        "git lfs install --force --local".split(),
        stderr=subprocess.PIPE,
        stdout=subprocess.PIPE,
        encoding="utf-8",
        check=True,
        cwd=local_dir,
    )

    # Push!
    subprocess.run(
        "git push --force origin main".split(),
        stderr=subprocess.PIPE,
        stdout=subprocess.PIPE,
        encoding="utf-8",
        check=True,
        cwd=local_dir,
    )

    # Clean up to be nice with the environment
    for filename in os.listdir(local_dir):
        file_path = os.path.join(local_dir, filename)
        if os.path.isfile(file_path) or os.path.islink(file_path):
            os.unlink(file_path)
        elif os.path.isdir(file_path):
            shutil.rmtree(file_path)

    # Same as above...
    if repo_type in ["space", "dataset"]:
        endpoint += "s"
    return endpoint + "/" + dst_repo


interface = gr.Interface(
    fn=fork,
    inputs=[
        gr.Textbox(placeholder="Source repository (e.g. osanseviero/src)"),
        gr.Textbox(placeholder="Destination repository (e.g. osanseviero/dst)"),
        gr.Textbox(placeholder="Write access token"),
        gr.Dropdown(choices=["model", "dataset", "space"]),
    ],
    outputs=["textbox"],
    title="Fork your repo!",
    description="Fork a Hugging Face repository! You need to specify a write token obtained in https://hf.co/settings/token. This Space is a an experimental demo.",
    article="<p>Find your write token at <a href='https://huggingface.co/settings/token' target='_blank'>token settings</a></p>",
    allow_flagging=False,
    live=False,
)
interface.launch()