package stream

import (
	"time"

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

// MediaInfo represents media stream information
type MediaInfo struct {
	Duration    time.Duration
	StartTime   time.Duration
	BitRate     int64
	Format      string
	FormatLong  string
	Streams     []*StreamInfo
}

// StreamInfo represents a single stream's information
type StreamInfo struct {
	Index          int
	Type          ffmpeg.CodecType
	CodecName     string
	CodecLongName string
	Width         int          // video only
	Height        int          // video only
	PixelFormat   string       // video only
	SampleRate    int          // audio only
	Channels      int          // audio only
	ChannelLayout string       // audio only
	FrameSize     int
	TimeBase      ffmpeg.Rational
	BitRate       int64
}

// NewMediaInfo creates MediaInfo from FormatContext
func NewMediaInfo(fc *ffmpeg.FormatContext) (*MediaInfo, error) {
	if fc == nil {
		return nil, nil
	}

	info := &MediaInfo{
		Streams: make([]*StreamInfo, 0),
	}

	// Get format info
	info.Duration = time.Duration(fc.Duration()) * time.Microsecond / 1000
	info.StartTime = time.Duration(fc.StartTime()) * time.Microsecond / 1000
	info.BitRate = fc.BitRate()

	// Get streams info
	streams := fc.Streams()
	for _, s := range streams {
		si := &StreamInfo{
			Index:    s.Index(),
			Type:     s.Type(),
			TimeBase: s.TimeBase(),
		}

		cp := s.CodecParameters()
		if cp != nil {
			si.CodecName = codecIDToName(cp.CodecID())
			si.CodecLongName = codecIDToLongName(cp.CodecID())
			si.BitRate = cp.BitRate()
			si.FrameSize = cp.FrameSize()

			switch si.Type {
			case ffmpeg.CodecTypeVideo:
				si.Width = cp.Width()
				si.Height = cp.Height()
				si.PixelFormat = pixelFormatToString(cp.Format())
			case ffmpeg.CodecTypeAudio:
				si.SampleRate = cp.SampleRate()
				si.Channels = cp.Channels()
				si.ChannelLayout = channelLayoutToString(cp.ChannelLayout())
			}
		}

		info.Streams = append(info.Streams, si)
	}

	return info, nil
}
