package main

import (
	"fmt"
	"log"
	"os"

	"git.kingecg.top/kingecg/goffmpeg/pkg/ffmpeg"
)

// Simple remuxing example using goffmpeg library
func main() {
	if len(os.Args) < 3 {
		fmt.Println("Usage: simple-transcode <input> <output>")
		fmt.Println("Example: simple-transcode input.mp4 output.flv")
		os.Exit(1)
	}

	inputURL := os.Args[1]
	outputURL := os.Args[2]

	// Open input file
	ic := ffmpeg.AllocFormatContext()
	defer ic.Free()

	if err := ic.OpenInput(inputURL); err != nil {
		log.Fatalf("Failed to open input %s: %v", inputURL, err)
	}

	// Find stream info
	if err := ic.FindStreamInfo(); err != nil {
		log.Fatalf("Failed to find stream info: %v", err)
	}

	fmt.Printf("Input: %s\n", inputURL)
	ic.DumpFormat(0, inputURL, false)

	// Guess output format
	of := ffmpeg.GuessFormat("", outputURL)
	if of == nil {
		log.Fatalf("Failed to guess output format")
	}

	// Create output context
	ofc, err := ffmpeg.AllocOutputContext(outputURL, of)
	if err != nil {
		log.Fatalf("Failed to allocate output context: %v", err)
	}
	defer ofc.Free()

	// Get input streams
	inputStreams := ic.Streams()

	// Process streams - select first video and audio only
	var videoIdx, audioIdx int = -1, -1
	streamCount := 0

	for i, is := range inputStreams {
		cp := is.CodecParameters()
		if cp == nil {
			continue
		}

		streamType := cp.CodecType()

		// Skip non-video/audio
		if streamType != ffmpeg.CodecTypeVideo && streamType != ffmpeg.CodecTypeAudio {
			continue
		}

		// Skip duplicate audio
		if streamType == ffmpeg.CodecTypeAudio && audioIdx >= 0 {
			fmt.Printf("\nStream %d: audio (skipped - duplicate)\n", i)
			continue
		}

		// Add stream with same codec (stream copy mode)
		os, err := ofc.AddStream(nil)
		if err != nil {
			fmt.Printf("\nStream %d: failed to add stream: %v\n", i, err)
			continue
		}

		// Copy codec parameters from input to output
		if err := os.SetCodecParameters(cp); err != nil {
			fmt.Printf("\nStream %d: failed to set codec parameters: %v\n", i, err)
			continue
		}

		// Copy time base
		tb := is.TimeBase()
		os.SetTimeBase(tb)

		if streamType == ffmpeg.CodecTypeVideo {
			videoIdx = streamCount
			fmt.Printf("\nStream %d: video (stream copy)\n", i)
		} else {
			audioIdx = streamCount
			fmt.Printf("\nStream %d: audio (stream copy)\n", i)
		}
		streamCount++
	}

	if videoIdx < 0 && audioIdx < 0 {
		log.Fatal("No supported streams found")
	}

	fmt.Printf("\nOutput: %s\n", outputURL)
	fmt.Printf("Output has %d streams\n", streamCount)
	ofc.DumpFormat(0, outputURL, true)

	// Open output file
	if err := ofc.OpenOutput(outputURL); err != nil {
		log.Fatalf("Failed to open output: %v", err)
	}

	// Write header
	if err := ofc.WriteHeader(); err != nil {
		log.Fatalf("Failed to write header: %v", err)
	}

	fmt.Println("\nRemuxing...")
	pkt := ffmpeg.AllocPacket()
	defer pkt.Free()

	packetCount := 0
	for {
		err := ic.ReadPacket(pkt)
		if err != nil {
			break
		}

		pktStreamIdx := pkt.StreamIndex()

		// Map input stream index to output stream index
		var outStreamIdx int
		if videoIdx >= 0 && audioIdx >= 0 {
			// Both video and audio present
			if pktStreamIdx == 0 {
				outStreamIdx = videoIdx
			} else if pktStreamIdx == 1 {
				outStreamIdx = audioIdx
			} else {
				pkt.Unref()
				continue
			}
		} else if videoIdx >= 0 {
			outStreamIdx = videoIdx
		} else {
			outStreamIdx = audioIdx
		}

		pkt.SetStreamIndex(outStreamIdx)

		if err := ofc.WritePacket(pkt); err != nil {
			log.Printf("Warning: failed to write packet: %v", err)
		}

		pkt.Unref()
		packetCount++

		if packetCount%100 == 0 {
			fmt.Printf("Processed %d packets...\n", packetCount)
		}
	}

	// Write trailer
	if err := ofc.WriteTrailer(); err != nil {
		log.Fatalf("Failed to write trailer: %v", err)
	}

	fmt.Printf("\nRemuxing complete! Processed %d packets.\n", packetCount)
	fmt.Printf("Output saved to: %s\n", outputURL)
}
