package urlline

import (
	"bufio"
	"bytes"
	"github.com/v2fly/v2ray-core/v5/app/subscription/containers"
	"github.com/v2fly/v2ray-core/v5/common"
	"net/url"
	"strings"
)

func newURLLineParser() containers.SubscriptionContainerDocumentParser {
	return &parser{}
}

type parser struct{}

func (p parser) ParseSubscriptionContainerDocument(rawConfig []byte) (*containers.Container, error) {
	result := &containers.Container{}
	result.Kind = "URLLine"
	result.Metadata = make(map[string]string)

	scanner := bufio.NewScanner(bytes.NewReader(rawConfig))

	const maxCapacity int = 1024 * 256
	buf := make([]byte, maxCapacity)
	scanner.Buffer(buf, maxCapacity)

	parsedLine := 0
	failedLine := 0

	for scanner.Scan() {
		content := scanner.Text()
		content = strings.TrimSpace(content)
		if strings.HasPrefix(content, "#") {
			continue
		}
		if strings.HasPrefix(content, "//") {
			continue
		}
		_, err := url.Parse(content)
		if err != nil {
			failedLine++
			continue
		} else {
			parsedLine++
		}
		result.ServerSpecs = append(result.ServerSpecs, containers.UnparsedServerConf{
			KindHint: "URL",
			Content:  scanner.Bytes(),
		})
	}

	if failedLine > parsedLine || parsedLine == 0 {
		return nil, newError("failed to parse as URLLine").Base(newError("too many failed lines"))
	}

	return result, nil
}

func init() {
	common.Must(containers.RegisterParser("URLLine", newURLLineParser()))
}
