from gitme import app

import os
import config
import flask
import git
import subprocess


@app.route("/git/<username>/<repository>/<path:git_path>", methods=["GET", "POST"])
def git_http_backend(username, repository, git_path):
    repo_path = os.path.join(config.REPOS_PATH, username, repository, ".git")
    repo = git.Repo(repo_path)
    git_cmd = repo.git

    if flask.request.method == "GET":
        result = git_cmd.upload_pack()
    elif flask.request.method == "POST":
        result = git_cmd.receive_pack()

    response = flask.Response(result, content_type="application/x-git-" + git_cmd[-1])
    return response


@app.route("/git/<username>/<repository>/info/refs")
def gitInfoRefs(username, repository):
    serverRepoLocation = os.path.join(config.REPOS_PATH, os.path.join(username, repository))

    app.logger.info(f"Loading {serverRepoLocation}")

    if not os.path.exists(serverRepoLocation):
        app.logger.error(f"Cannot load {serverRepoLocation}")
        flask.abort(404)

    repo = git.Repo(serverRepoLocation)
    text = f"{repo.heads[0].commit.hexsha}\tHEAD\n"
    for ref in repo.heads:
        text += f"{ref.commit.hexsha}\trefs/heads/{ref.name}\n"

    app.logger.warning(text)

    return flask.Response(text, content_type="application/x-git-upload-pack-result")


@app.route("/git/<username>/<repository>/objects/info/alternates", methods=["GET"])
def gitInfoAlternates(username, repository):
    # Handle the request and provide the response
    text = "#Alternate object stores\n"

    return flask.Response(text, content_type="text/plain")


@app.route("/git/<username>/<repository>/objects/info/http-alternates")
def gitHttpAlternates(username, repository):
    # Return an empty response
    return flask.Response("", content_type="text/plain")


@app.route("/git/<username>/<repository>/HEAD")
def gitHead(username, repository):
    serverRepoLocation = os.path.join(config.REPOS_PATH, os.path.join(username, repository))

    app.logger.info(f"Loading {serverRepoLocation}")

    if not os.path.exists(serverRepoLocation):
        app.logger.error(f"Cannot load {serverRepoLocation}")
        flask.abort(404)

    repo = git.Repo(serverRepoLocation)

    text = f"ref: {repo.head.ref}\n"

    return flask.Response(text, content_type="text/plain")


@app.route("/git/<username>/<repository>/objects/info/packs")
def gitInfoPacks(username, repository):
    repo_path = os.path.join(config.REPOS_PATH, username, repository)

    # List the pack files in the repository
    packs = [f for f in os.listdir(os.path.join(repo_path, "objects", "pack")) if f.endswith(".pack")]

    # Generate a response with the list of pack files
    response_text = "\n".join(packs) + "\n"

    return flask.Response(response_text, content_type="text/plain")


@app.route("/git/<username>/<repository>/objects/<path:object_path>")
def gitObject(username, repository, object_path):
    repo_path = os.path.join(config.REPOS_PATH, username, repository)
    object_full_path = os.path.join(repo_path, ".git/objects", object_path)

    # Check if the object file exists
    if not os.path.exists(object_full_path):
        return flask.Response("Object not found", status=404, content_type="text/plain")

    # Serve the object as binary data
    with open(object_full_path, "rb") as object_file:
        object_data = object_file.read()

    return flask.Response(object_data, content_type="application/octet-stream")


@app.route("/git/<username>/<repository>/git-upload-pack", methods=["POST"])
def gitUploadPack(username, repository):
    repoPath = "/path/to/repos/{}/{}/".format(username, repository)
    cmd = ["git", "--git-dir", repoPath, "upload-pack"]

    gitProcess = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

    # Forward the Git process input and output
    inputData = flask.request.get_data()
    output = gitProcess.communicate(input=inputData)
    return flask.Response(output[0], content_type="application/x-git-upload-pack-result")


@app.route("/git/<username>/<repository>/git-receive-pack", methods=["POST"])
def gitReceivePack(username, repository):
    repoPath = "/path/to/repos/{}/{}/".format(username, repository)
    cmd = ["git", "--git-dir", repoPath, "receive-pack"]

    gitProcess = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

    # Forward the Git process input and output
    inputData = flask.request.get_data()
    output = gitProcess.communicate(input=inputData)
    return flask.Response(output[0], content_type="application/x-git-receive-pack-result")
