package util

import (
	"context"

	logpattern_go_proto "github.com/pingcap-inc/alioth/proto"
	"github.com/pingcap-inc/alioth/storage"
)

func CloneLogPatternStore(ctx context.Context, source *storage.LogPatternStore, target *storage.LogPatternStore) error {
	return source.ScanLogPattern(ctx, func(_, value []byte) error {
		lp := &logpattern_go_proto.LogPattern{}
		err := lp.Unmarshal(value)
		if err != nil {
			return err
		}

		return target.WriteLogPattern(ctx, lp)
	})
}

func CloneLogPattern(source *logpattern_go_proto.LogPattern) *logpattern_go_proto.LogPattern {
	pattern := &logpattern_go_proto.LogPattern{
		Level:      source.Level,
		Signature:  make([]string, 0, len(source.Signature)),
		Pos:        ClonePosition(source.Pos),
		IsDeferLog: source.IsDeferLog,
	}

	if source.Func != nil {
		fn := source.Func
		pattern.Func = &logpattern_go_proto.FuncInfo{
			Name: fn.Name,
			Pos:  ClonePosition(fn.Pos),
		}
		if len(fn.Code) > 0 {
			pattern.Func.Code = append([]byte{}, fn.Code...)
		}
	}

	for _, signature := range source.Signature {
		pattern.Signature = append(pattern.Signature, signature)
	}

	return pattern
}

func ClonePosition(source *logpattern_go_proto.Position) *logpattern_go_proto.Position {
	if source == nil {
		return nil
	}
	pos := &logpattern_go_proto.Position{
		FilePath: source.FilePath,
	}

	if source.PackageInfo != nil {
		pos.PackageInfo = &logpattern_go_proto.Package{
			Repo: source.PackageInfo.Repo,
			Path: source.PackageInfo.Path,
			Hash: source.PackageInfo.Hash,
			Tag:  source.PackageInfo.Tag,
		}
	}

	if source.Pos != nil {
		pos.Pos = &logpattern_go_proto.CodePosition{
			Line:   source.Pos.Line,
			Column: source.Pos.Column,
		}
	}

	if source.EndPos != nil {
		pos.EndPos = &logpattern_go_proto.CodePosition{
			Line:   source.EndPos.Line,
			Column: source.EndPos.Column,
		}
	}

	return pos
}

func CompareVersion(version string, pos *logpattern_go_proto.Position) bool {
	if version == "" {
		return true
	}

	if pos == nil || pos.PackageInfo == nil {
		return false
	}

	return version == pos.PackageInfo.Hash || version == pos.PackageInfo.Tag
}
