import { valueToTreeObject } from "./value-to-tree-object";
export async function createTree(state, changes) {
    const { octokit, owner, repo, ownerOrFork, latestCommitSha, latestCommitTreeSha, } = state;
    const tree = (await Promise.all(Object.keys(changes.files).map(async (path) => {
        const value = changes.files[path];
        if (value === null) {
            // Deleting a non-existent file from a tree leads to an "GitRPC::BadObjectState" error,
            // so we only attempt to delete the file if it exists.
            try {
                // https://developer.github.com/v3/repos/contents/#get-contents
                await octokit.request("HEAD /repos/{owner}/{repo}/contents/:path", {
                    owner: ownerOrFork,
                    repo,
                    ref: latestCommitSha,
                    path,
                });
                return {
                    path,
                    mode: "100644",
                    sha: null,
                };
            }
            catch (error) {
                return;
            }
        }
        // When passed a function, retrieve the content of the file, pass it
        // to the function, then return the result
        if (typeof value === "function") {
            let result;
            try {
                const { data: file } = await octokit.request("GET /repos/{owner}/{repo}/contents/:path", {
                    owner: ownerOrFork,
                    repo,
                    ref: latestCommitSha,
                    path,
                });
                result = await value(Object.assign(file, { exists: true }));
            }
            catch (error) {
                // istanbul ignore if
                if (error.status !== 404)
                    throw error;
                // @ts-ignore
                result = await value({ exists: false });
            }
            if (result === null || typeof result === "undefined")
                return;
            return valueToTreeObject(octokit, ownerOrFork, repo, path, result);
        }
        return valueToTreeObject(octokit, ownerOrFork, repo, path, value);
    }))).filter(Boolean);
    if (tree.length === 0) {
        return null;
    }
    // https://developer.github.com/v3/git/trees/#create-a-tree
    const { data: { sha: newTreeSha }, } = await octokit.request("POST /repos/{owner}/{repo}/git/trees", {
        owner: ownerOrFork,
        repo,
        base_tree: latestCommitTreeSha,
        tree,
    });
    return newTreeSha;
}
