package parsers

import (
	"regexp"

	"git.tordarus.net/nyaanime/model"
)

// TorrentParseOptions holds the subgroup index in which information can be found in a given regex
// as well as some parser specific functions
type TorrentParseOptions struct {
	// regex group references
	Name       int
	Episode    int
	Languages  int
	Subtitles  int
	Resolution int

	// language parsers
	LanguageParser LanguageParserFunc
	SubtitleParser LanguageParserFunc

	// default values used when group reference is 0
	DefaultLanguages  []string
	DefaultSubtitles  []string
	DefaultResolution model.Resolution
}

func RegexTorrentParser(regex string, options TorrentParseOptions) model.TorrentParserFunc {
	pattern := regexp.MustCompile(regex)

	// handle faulty regexes
	if options.Name == 0 || options.Episode == 0 {
		panic(ErrTorrentParserInsufficientData.New(regex))
	} else if options.Languages == 0 && options.DefaultLanguages == nil {
		panic(ErrTorrentParserInsufficientLanguageData.New(regex))
	} else if options.Subtitles == 0 && options.DefaultSubtitles == nil {
		panic(ErrTorrentParserInsufficientSubtitleData.New(regex))
	} else if options.Resolution == 0 && options.DefaultResolution == 0 {
		panic(ErrTorrentParserInsufficientResolutionData.New(regex))
	}

	// handle faulty group references
	for _, g := range []int{options.Name, options.Episode, options.Languages, options.Subtitles, options.Resolution} {
		if g > pattern.NumSubexp() {
			panic(ErrTorrentParserInvalidGroupReference.New(g, pattern.NumSubexp()))
		}
	}

	return func(parser *model.Parser, torrent *model.Torrent) (ParsedTorrent *model.ParsedTorrent, ok bool) {
		var err error

		matches := pattern.FindStringSubmatch(torrent.Title)

		if matches == nil {
			return nil, false
		}

		episode, ok := atoi(matches[options.Episode])
		if !ok {
			return nil, false
		}

		resolution := options.DefaultResolution
		if options.Resolution != 0 {
			resolution, err = model.ParseResolution(matches[options.Resolution])
			if err != nil {
				return nil, false
			}
		}

		languages := options.DefaultLanguages
		if options.Languages != 0 {
			languages = options.LanguageParser(matches[options.Languages])
		}

		subtitles := options.DefaultSubtitles
		if options.Subtitles != 0 {
			subtitles = options.SubtitleParser(matches[options.Subtitles])
		}

		return &model.ParsedTorrent{
			OriginalAnimeTitle: matches[options.Name],
			Episode:            episode,
			Resolution:         resolution,
			Parser:             parser,
			Languages:          ParseLanguages(languages),
			Subtitles:          ParseLanguages(subtitles),

			Torrent: torrent,
		}, true
	}
}