// Recipe "paging": read every document, a page at a time, in object ID order.
//
// Usage: go run ./recipes/paging [page size, default 100]
package main

import (
	"context"
	"fmt"

	"github.com/M-Files/mfiles-grpc-api-samples/mfilesclient"
	"github.com/M-Files/mfiles-grpc-api-samples/recipes/internal/recipe"
	"github.com/M-Files/mfiles-grpc-api/go/mfiles"
)

// sortByObjectID is the sort key for ascending object ID order.
const sortByObjectID = -102

func main() {
	recipe.Main(run)
}

func run(ctx context.Context) error {
	pageSize := recipe.IntArg(0, 100)
	client, err := recipe.Connect(ctx)
	if err != nil {
		return err
	}
	defer client.Close()
	search := mfiles.NewIRPCSearchClient(client.Conn)

	// [START paging]
	// Keyset paging: sort by object ID and ask each page for IDs above the last one seen.
	var lastID, page, total int32
	for {
		response, err := search.SearchObjects(ctx, &mfiles.SearchObjectsRequest{
			Conditions: mfilesclient.AllOf(
				mfilesclient.IsObjectType(0),
				mfilesclient.IsNotDeleted(),
				mfilesclient.StatusCondition(mfiles.StatusType_STATUS_TYPE_OBJECT_ID,
					mfiles.ConditionType_CONDITION_TYPE_GREATER_THAN, mfilesclient.Integer(lastID)),
			),
			Sorting: mfilesclient.SortBy(sortByObjectID, false),
			Limit:   uint32(pageSize),
		})
		if err != nil {
			return err
		}
		results := response.GetResults()
		if len(results) == 0 {
			break
		}

		page++
		total += int32(len(results))
		firstID := objectID(results[0])
		lastID = objectID(results[len(results)-1])
		fmt.Printf("Page %d: %d documents, IDs %d-%d\n", page, len(results), firstID, lastID)

		if !response.GetHasMoreResults() {
			break
		}
	}
	// [END paging]
	fmt.Printf("Total: %d documents in %d pages\n", total, page)
	return nil
}

func objectID(item *mfiles.SearchResultsItem) int32 {
	return item.GetObject().GetObjectInfo().GetObjId().GetItemId().GetInternalId()
}
