// -=-=- StartHere -=-=-
//
// # Chapter XII: Following redirections.
//
// This program shows how to combine the URL measurement
// "step" introduced in the previous chapter with
// following redirections. If we say that the previous
// chapter performed a "web step", then we can say
// that here we're performing multiple "web steps".
//
// (This file is auto-generated. Do not edit it directly! To apply
// changes you need to modify `./internal/tutorial/measurex/chapter12/main.go`.)
//
// ## main.go
//
// The beginning of the program is pretty much the
// same, except that here we need to define a
// `measurement` container type that will contain
// the result of each "web step".
//
// ```Go
package main

import (
	"context"
	"encoding/json"
	"flag"
	"fmt"
	"time"

	"github.com/ooni/probe-cli/v3/internal/measurex"
	"github.com/ooni/probe-cli/v3/internal/runtimex"
)

type measurement struct {
	URLs []*measurex.ArchivalURLMeasurement
}

func print(v interface{}) {
	data, err := json.Marshal(v)
	runtimex.PanicOnError(err, "json.Marshal failed")
	fmt.Printf("%s\n", string(data))
}

func main() {
	URL := flag.String("url", "http://facebook.com/", "URL to fetch")
	timeout := flag.Duration("timeout", 60*time.Second, "timeout to use")
	flag.Parse()
	ctx, cancel := context.WithTimeout(context.Background(), *timeout)
	defer cancel()
	all := &measurement{}
	mx := measurex.NewMeasurerWithDefaultSettings()
	cookies := measurex.NewCookieJar()
	headers := measurex.NewHTTPRequestHeaderForMeasuring()
	// ```
	//
	// Everything above this line is like in chapter11. What changes
	// now is that we're calling `MeasureURLAndFollowRedirections`
	// instead of `MeasureURL`.
	//
	// Rather than returning a single measurement, this function
	// returns a channel where it posts the result of measuring
	// the original URL along with all its redirections. Internally,
	// `MeasureURLAndFollowRedirections` calls `MeasureURL`.
	//
	// The parallelism argument dictates how many parallel goroutine
	// to use for parallelizable operations. (A zero or negative
	// value implies that the code should use a sensible default value.)
	//
	// We accumulate the results in `URLs` and print `m`. The channel
	// is closed when done by `MeasureURLAndFollowRedirections`, so we leave the loop.
	//
	// ```Go
	const parallelism = 3
	for m := range mx.MeasureURLAndFollowRedirections(ctx, parallelism, *URL, headers, cookies) {
		all.URLs = append(all.URLs, measurex.NewArchivalURLMeasurement(m))
	}
	print(all)
}

// ```
//
// ## Running the example program
//
// Let us perform a vanilla run first:
//
// ```bash
// go run -race ./internal/tutorial/measurex/chapter12 | jq
// ```
//
// Take a look at the JSON. You should see several redirects
// and that we measure each endpoint of each redirect, including
// QUIC endpoints that we discover on the way.
//
// Exercise: remove code for converting to OONI data format
// and compare output with previous chapter. See any difference?
//
// ## Conclusion
//
// We have introduced `MeasureURLAndFollowRedirect`, the
// top-level API for fully measuring a URL and all the URLs
// that derive from such an URL via redirection.
//
// -=-=- StopHere -=-=-