package types

import (
	"fmt"

	"gitlink.org.cn/cloudream/common/utils/lo2"
)

type RequestID string

type Lock struct {
	Path   []string   // 锁路径，存储的是路径的每一部分
	Name   string     // 锁名
	Target LockTarget // 锁对象，由具体的Provider去解析
}

func (b *Lock) Equals(other Lock) bool {
	return lo2.ArrayEquals(b.Path, other.Path) && b.Name == other.Name && b.Target.Equals(other.Target)
}

type LockTarget interface {
	Equals(other LockTarget) bool
}

type LockRequest struct {
	Reason string
	Locks  []Lock
}

func (b *LockRequest) Add(lock Lock) {
	b.Locks = append(b.Locks, lock)
}

type LockProvider interface {
	// CanLock 判断这个锁能否锁定成功
	CanLock(lock Lock) error

	// Lock 锁定。由于同一个锁请求内的锁不检查冲突，因此这个函数必须支持有冲突的锁进行锁定。
	Lock(reqID RequestID, lock Lock) error

	// 解锁
	Unlock(reqID RequestID, lock Lock) error

	// Clear 清除内部所有状态
	Clear()
}

type LockTargetBusyError struct {
	lockName string
}

func (e *LockTargetBusyError) Error() string {
	return fmt.Sprintf("the lock object is locked by %s", e.lockName)
}

func NewLockTargetBusyError(lockName string) *LockTargetBusyError {
	return &LockTargetBusyError{
		lockName: lockName,
	}
}
