from gitmanip import Project as GitProject
import json
from datetime import datetime
import time

def process_request(**kwargs):
    project_name = kwargs.get("project", None)
    # TODO
    # if project_name is None:
    #     raise HTTP404()

    project = GitProject(project_name)
    branch_name = kwargs.get("branch", "master")
    branch = project.get_branch(branch_name)

    filelist = branch.get_filelist("")
    commits = {}
    output_tree = {
        "_i": {},
        "name": "",
        "parent": None,
        "commit": None,
        "folders": [],
        "files": []
    }

    # offset = len(path)
    for file_path, commit_id in filelist:
        parts = file_path.split("/")
        if commit_id not in commits:
            commit = branch.get_commit(commit_id)
            commits[commit_id] = {
                "id": commit_id, 
                "description": commit.get_description(),
                "date": commit.date.timestamp()
            }
        stack = [(output_tree, parts)]
        while stack:
            working_tree, working_parts = stack.pop(0)
            if len(working_parts) > 0:
                next_node = working_parts[0]
                if next_node in working_tree["_i"].keys():
                    index = working_tree["_i"][next_node]
                else:
                    if len(working_parts) == 1:
                        working_tree["files"].append({
                            "name": next_node, 
                            "commit": commit_id,
                        })
                        continue


                    index = len(working_tree["folders"])
                    working_tree["folders"].append({
                        "name": [working_parts[0]],
                        "_i": {},
                        "commit": None,
                        "parent": working_tree,
                        "folders": [],
                        "files": []
                    })
                    working_tree["_i"][next_node] = index
                
                stack.append((working_tree["folders"][index], working_parts[1:]))

    stack = [output_tree]
    while stack:
        working_tree = stack.pop(0)

        # Climb and replace commit ids with most recent
        while working_tree:
            latest_file_commit = None
            latest_file_commit_id = None
            for f in working_subtree["files"]:
                if latest_file_commit is None:
                    latest_file_commit_id = f["commit"]
                    latest_file_commit = commits[latest_file_commit_id]
                else:
                    working_file_commit_id = f["commit"]
                    working_file_commit = commits[working_file_commit_id]
                    if latest_file_commit["date"] > working_file_commit["date"]:
                        latest_file_commit = working_file_commit
                        latest_file_commit_id = working_file_commit_id

            if working_tree["commit"] is None or commits[working_tree["commit"]]["date"] < latest_file_commit["date"]:
                working_tree["commit"] = latest_file_commit_id
                working_tree = working_tree["parent"]
            else:
                break

    stack = [output_tree]
    while stack:
        working_tree = stack.pop(0)
        for subtree in working_tree["folders"]:
            stack.append(subtree)
        del working_tree["_i"]
        del working_tree["parent"]


    return {
        "branch": branch_name,
        "tree": output_tree,
        "commits": commits
    }
