package redislock

import (
	"fmt"
	"sync"
	"testing"
	"time"
)

func TestLock(t *testing.T) {
	lock, err := NewLock("localhost:30379", "mtyzxhc", 0)
	if err != nil {
		t.Fatal(err)
	}

	defer func(lock *Lock) {
		err := DestroyLock(lock)
		if err != nil {
			t.Fatal(err)
		}
	}(lock)

	wg := sync.WaitGroup{}
	wg.Add(5)

	for i := 0; i < 5; i++ {
		go func(index int) {
			err := lock.Lock("test", "test", 60)
			if err != nil {
				panic(err)
			}

			fmt.Println("Lock: ", index, "Time: ", time.Now())

			time.Sleep(1 * time.Second)

			err = lock.Unlock("test", "test")
			if err != nil {
				panic(err)
			}

			fmt.Println("Unlock: ", index, "Time: ", time.Now())

			wg.Done()
		}(i)
	}

	wg.Wait()
}

func TestTryLock(t *testing.T) {
	lock, err := NewLock("localhost:30379", "mtyzxhc", 0)
	if err != nil {
		t.Fatal(err)
	}

	defer func(lock *Lock) {
		err := DestroyLock(lock)
		if err != nil {
			t.Fatal(err)
		}
	}(lock)

	wg := sync.WaitGroup{}
	wg.Add(2)

	go func() {
		err := lock.Lock("test", "test", 60)
		if err != nil {
			panic(err)
		}

		fmt.Println("Lock: ", 1, "Time: ", time.Now())

		time.Sleep(6 * time.Second)

		err = lock.Unlock("test", "test")
		if err != nil {
			panic(err)
		}

		fmt.Println("Unlock: ", 1, "Time: ", time.Now())

		wg.Done()
	}()

	time.Sleep(1 * time.Second)

	go func() {
		for {
			locked, err := lock.TryLock("test", "test", 60)
			if err != nil {
				panic(err)
			}

			if !locked {
				fmt.Println("TryLock Failed: ", 2, "Time: ", time.Now())
				time.Sleep(1 * time.Second)
				continue
			}

			fmt.Println("Lock: ", 2, "Time: ", time.Now())

			err = lock.Unlock("test", "test")
			if err != nil {
				panic(err)
			}

			fmt.Println("Unlock: ", 2, "Time: ", time.Now())

			break
		}

		wg.Done()
	}()

	wg.Wait()
}