package main

import (
	"context"
	"flag"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"strings"
	"sync"
	"time"

	"git.netflux.io/rob/clipper/media"

	youtubev2 "github.com/kkdai/youtube/v2"
)

func main() {
	var (
		verbose      bool
		printMode    bool
		downloadMode bool
		audioOnly    bool
		videoOnly    bool
	)
	flag.BoolVar(&verbose, "v", false, "verbose output")
	flag.BoolVar(&printMode, "print", true, "print format info")
	flag.BoolVar(&downloadMode, "download", false, "download all media to ./debug")
	flag.BoolVar(&audioOnly, "audio", false, "only print audio formats")
	flag.BoolVar(&videoOnly, "video", false, "only print video formats")
	flag.Parse()

	videoID := flag.Arg(0)
	ctx := context.Background()
	var youtubeClient youtubev2.Client

	video, err := youtubeClient.GetVideoContext(ctx, videoID)
	if err != nil {
		log.Fatal(err)
	}
	formats := video.Formats

	if downloadMode {
		downloadAll(formats)
		return
	}

	switch {
	case audioOnly:
		formats = media.FilterYoutubeAudio(formats)
	case videoOnly:
		formats = media.FilterYoutubeVideo(formats)
	}

	fmt.Println("In descending order of preference:")
	for n, f := range formats {
		fmt.Printf("%d: %s\n", n+1, formatDebugString(&f, verbose))
	}
}

func downloadAll(formats youtubev2.FormatList) {
	var wg sync.WaitGroup

	for i := range formats {
		format := formats[i]
		wg.Add(1)
		go func() {
			defer wg.Done()
			start := time.Now()

			outpath := fmt.Sprintf("./debug/%s.%s-itag-%d", strings.ReplaceAll(format.MimeType, "/", "'"), format.Quality, format.ItagNo)
			output, err := os.Create(outpath)
			if err != nil {
				log.Fatalf("error opening output file: %v", err)
			}

			resp, err := http.Get(format.URL)
			if err != nil {
				log.Fatalf("error fetching media: %v", err)
			}
			defer resp.Body.Close()

			n, err := io.Copy(output, resp.Body)
			if err != nil {
				log.Fatalf("error reading media: %v", err)
			}

			dur := time.Since(start)
			log.Printf("downloaded itag %d, %d bytes in %v secs", format.ItagNo, n, dur.Seconds())
		}()
	}

	wg.Wait()
}

func formatDebugString(format *youtubev2.Format, includeURL bool) string {
	url := "hidden"
	if includeURL {
		url = format.URL
	}
	return fmt.Sprintf(
		"iTag = %d, mime_type = %s, quality = %s, quality_label = %s, bitrate = %d, fps = %d, width = %d, height = %d, content_length = %d, duration = %v, audio_channels = %d, audio_sample_rate = %s, audio_quality = %s, url = %s",
		format.ItagNo,
		format.MimeType,
		format.Quality,
		format.QualityLabel,
		format.Bitrate,
		format.FPS,
		format.Width,
		format.Height,
		format.ContentLength,
		format.ApproxDurationMs,
		format.AudioChannels,
		format.AudioSampleRate,
		format.AudioQuality,
		url,
	)
}
