package utils

import (
	"fmt"
	"github.com/h2non/filetype"
	"github.com/h2non/filetype/types"
	"strings"
	"sync"
)

type SourceType string

const (
	Image    SourceType = "image"
	Video    SourceType = "video"
	Archive  SourceType = "archive"
	Audio    SourceType = "audio"
	Document SourceType = "document"
)

func CheckFileType(buf []byte, sourceType SourceType, exactFileType []string, fileExt string) bool {
	switch sourceType {
	case Document:
		kind, err := filetype.Document(buf)
		if err != nil {
			return false
		}
		return exactFile(exactFileType, kind, fileExt)
	case Image:
		kind, err := filetype.Image(buf)
		if err != nil {
			return false
		}
		return exactFile(exactFileType, kind, fileExt)
	case Video:
		kind, err := filetype.Video(buf)
		if err != nil {
			return false
		}
		return exactFile(exactFileType, kind, fileExt)
	case Audio:
		kind, err := filetype.Audio(buf)
		if err != nil {
			return false
		}
		return exactFile(exactFileType, kind, fileExt)
	case Archive:
		kind, err := filetype.Archive(buf)
		if err != nil {
			return false
		}
		return exactFile(exactFileType, kind, fileExt)
	default:
		return false
	}
}
func exactFile(exactFileType []string, fileKind types.Type, fileExt string) bool {
	lowCase := strings.ToLower(fileExt)
	for _, fileType := range exactFileType {
		if fileKind.Extension == fileType {
			if lowCase != "" && (lowCase == fmt.Sprintf(".%s", fileKind.Extension) || (lowCase == ".jpeg" && fileKind.Extension == "jpg")) {
				return true
			}
			return false
		}
	}
	return false
}
func IsValidType(buf []byte, sourceTypes []SourceType, exactFileType []string, fileExt string) bool {
	if len(sourceTypes) == 0 {
		return false
	}
	var wg sync.WaitGroup
	resultChan := make(chan bool, len(sourceTypes))
	for _, sourceType := range sourceTypes {
		wg.Add(1)
		go func(st SourceType) {
			defer wg.Done()
			resultChan <- CheckFileType(buf, st, exactFileType, fileExt)
		}(sourceType)
	}
	wg.Wait()
	close(resultChan)
	for result := range resultChan {
		if result {
			return true
		}
	}
	return false
}