package distlock

import "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/distlock/types"

type Reentrant struct {
	svc    *Service
	reqs   []types.LockRequest
	locked []*Mutex
}

func (r *Reentrant) Lock(req types.LockRequest, opt ...AcquireOptionFn) error {
	var willLock []types.Lock

loop:
	for _, lock := range req.Locks {
		for _, req := range r.reqs {
			for _, locked := range req.Locks {
				if locked.Equals(lock) {
					continue loop
				}
			}
		}

		willLock = append(willLock, lock)
	}

	if len(willLock) == 0 {
		return nil
	}

	newReq := types.LockRequest{
		Reason: req.Reason,
		Locks:  willLock,
	}

	m, err := r.svc.Acquire(newReq, opt...)
	if err != nil {
		return err
	}

	r.reqs = append(r.reqs, newReq)
	r.locked = append(r.locked, m)

	return nil
}

func (r *Reentrant) Unlock() {
	for i := len(r.reqs) - 1; i >= 0; i-- {
		r.locked[i].Unlock()
	}
	r.locked = nil
	r.reqs = nil
}
