package main

import (
	"errors"
	"sort"
	"strings"
)

type tagFilter struct {
	emit []string
	skip []string
}

func newTagFilter(tags string) (tagFilter, error) {
	if tags == "" {
		return tagFilter{}, nil
	}

	skipFilter := tags[0] == '-'
	if skipFilter {
		tags = tags[1:]
	}

	tt := strings.Split(tags, ",")
	if err := checkTags(tt); err != nil {
		return tagFilter{}, err
	}

	if skipFilter {
		return tagFilter{skip: tt}, nil
	}
	return tagFilter{emit: tt}, nil

}

func (tf tagFilter) shouldEmit(tag string) bool {
	emitMode := len(tf.emit) > 0
	skipMode := len(tf.skip) > 0
	switch {
	case !emitMode && !skipMode:
		return true
	case emitMode:
		return stringSliceContains(tf.emit, tag)
	case skipMode:
		return !stringSliceContains(tf.skip, tag)
	}
	return false // will never get here
}

func checkTags(tags []string) error {
	if len(tags) == 0 {
		return nil
	}
	var invalid []string
	for _, t := range tags {
		if t == "" {
			continue
		}
		if !validTags[t] {
			invalid = append(invalid, t)
		}
	}
	if len(invalid) > 0 {
		return errors.New(strings.Join(invalid, ", "))
	}
	return nil
}

func knownTags() []string {
	var tags []string
	for t := range validTags {
		tags = append(tags, t)
	}
	sort.StringSlice(tags).Sort()
	return tags
}

var (
	validTags = map[string]bool{
		BROKEN_SYMLINK_TAG:             true,
		MISSING_ALTERNATIVE_TAG:        true,
		MISSING_COPYRIGHT_FILE_TAG:     true,
		MISSING_PKGCONF_DEPENDENCY_TAG: true,
		NAME_COLLISION_TAG:             true,
		OBSOLETE_CONFFILE_TAG:          true,

		// binfmt
		BROKEN_BINFMT_DETECTOR_TAG:    true,
		BROKEN_BINFMT_INTERPRETER_TAG: true,

		// python
		PYFILE_NOT_BYTECOMPILED_TAG:        true,
		PYSHARED_FILE_NOT_BYTECOMPILED_TAG: true,

		// elf
		BIN_OR_SBIN_BINARY_REQUIRES_USR_LIB_LIBRARY_TAG: true,
		INCOMPATIBLE_LICENSES_TAG:                       true,
		LDD_FAILURE_TAG:                                 true,
		LIBRARY_NOT_FOUND_TAG:                           true,
		MISSING_SYMBOL_VERSION_INFORMATION_TAG:          true,
		SYMBOL_SIZE_MISMATCH_TAG:                        true,
		UNDEFINED_SYMBOL_TAG:                            true,

		// system ids
		INVALID_SYSTEMD_USER_GROUP_TAG:   true,
		INVALID_DBUS_USER_GROUP_TAG:      true,
		INVALID_SYSV_INIT_USER_GROUP_TAG: true,
	}
)
