// Copyright 2013 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package github

import (
	
	
	
)

// Tree represents a GitHub tree.
type Tree struct {
	SHA     *string      `json:"sha,omitempty"`
	Entries []*TreeEntry `json:"tree,omitempty"`

	// Truncated is true if the number of items in the tree
	// exceeded GitHub's maximum limit and the Entries were truncated
	// in the response. Only populated for requests that fetch
	// trees like Git.GetTree.
	Truncated *bool `json:"truncated,omitempty"`
}

func ( Tree) () string {
	return Stringify()
}

// TreeEntry represents the contents of a tree structure. TreeEntry can
// represent either a blob, a commit (in the case of a submodule), or another
// tree.
type TreeEntry struct {
	SHA     *string `json:"sha,omitempty"`
	Path    *string `json:"path,omitempty"`
	Mode    *string `json:"mode,omitempty"`
	Type    *string `json:"type,omitempty"`
	Size    *int    `json:"size,omitempty"`
	Content *string `json:"content,omitempty"`
	URL     *string `json:"url,omitempty"`
}

func ( TreeEntry) () string {
	return Stringify()
}

// treeEntryWithFileDelete is used internally to delete a file whose
// Content and SHA fields are empty. It does this by removing the "omitempty"
// tag modifier on the SHA field which causes the GitHub API to receive
// {"sha":null} and thereby delete the file.
type treeEntryWithFileDelete struct {
	SHA     *string `json:"sha"`
	Path    *string `json:"path,omitempty"`
	Mode    *string `json:"mode,omitempty"`
	Type    *string `json:"type,omitempty"`
	Size    *int    `json:"size,omitempty"`
	Content *string `json:"content,omitempty"`
	URL     *string `json:"url,omitempty"`
}

func ( *TreeEntry) () ([]byte, error) {
	if .SHA == nil && .Content == nil {
		return json.Marshal(struct {
			  *string `json:"sha"`
			 *string `json:"path,omitempty"`
			 *string `json:"mode,omitempty"`
			 *string `json:"type,omitempty"`
		}{
			nil,
			.Path,
			.Mode,
			.Type,
		})
	}
	return json.Marshal(struct {
		     *string `json:"sha,omitempty"`
		    *string `json:"path,omitempty"`
		    *string `json:"mode,omitempty"`
		    *string `json:"type,omitempty"`
		    *int    `json:"size,omitempty"`
		 *string `json:"content,omitempty"`
		     *string `json:"url,omitempty"`
	}{
		:     .SHA,
		:    .Path,
		:    .Mode,
		:    .Type,
		:    .Size,
		: .Content,
		:     .URL,
	})
}

// GetTree fetches the Tree object for a given sha hash from a repository.
//
// GitHub API docs: https://docs.github.com/rest/git/trees#get-a-tree
//
//meta:operation GET /repos/{owner}/{repo}/git/trees/{tree_sha}
func ( *GitService) ( context.Context,  string,  string,  string,  bool) (*Tree, *Response, error) {
	 := fmt.Sprintf("repos/%v/%v/git/trees/%v", , , )
	if  {
		 += "?recursive=1"
	}

	,  := .client.NewRequest("GET", , nil)
	if  != nil {
		return nil, nil, 
	}

	 := new(Tree)
	,  := .client.Do(, , )
	if  != nil {
		return nil, , 
	}

	return , , nil
}

// createTree represents the body of a CreateTree request.
type createTree struct {
	BaseTree string        `json:"base_tree,omitempty"`
	Entries  []interface{} `json:"tree"`
}

// CreateTree creates a new tree in a repository. If both a tree and a nested
// path modifying that tree are specified, it will overwrite the contents of
// that tree with the new path contents and write a new tree out.
//
// GitHub API docs: https://docs.github.com/rest/git/trees#create-a-tree
//
//meta:operation POST /repos/{owner}/{repo}/git/trees
func ( *GitService) ( context.Context,  string,  string,  string,  []*TreeEntry) (*Tree, *Response, error) {
	 := fmt.Sprintf("repos/%v/%v/git/trees", , )

	 := make([]interface{}, 0, len())
	for ,  := range  {
		if .Content == nil && .SHA == nil {
			 = append(, treeEntryWithFileDelete{
				Path: .Path,
				Mode: .Mode,
				Type: .Type,
				Size: .Size,
				URL:  .URL,
			})
			continue
		}
		 = append(, )
	}

	 := &createTree{
		BaseTree: ,
		Entries:  ,
	}
	,  := .client.NewRequest("POST", , )
	if  != nil {
		return nil, nil, 
	}

	 := new(Tree)
	,  := .client.Do(, , )
	if  != nil {
		return nil, , 
	}

	return , , nil
}