package main

import (
	"log"
	"sync"
	"time"
)

type SuperLock struct {
	self *sync.Mutex
	lock *sync.RWMutex
	sem  chan struct{}
}

func NewSuperLock() *SuperLock {
	return &SuperLock{
		sem:  make(chan struct{}, 100),
		self: &sync.Mutex{},
		lock: &sync.RWMutex{},
	}
}

func (sl *SuperLock) RLock() {
	log.Println("sl.rlock...")
	sl.lock.RLock()
}

func (sl *SuperLock) RUnlock() {
	log.Println("sl.runlock")
	sl.lock.RUnlock()
}

func (sl *SuperLock) Lock() {
	log.Println("sl.lock...")
	sl.lock.Lock()
}

func (sl *SuperLock) Unlock() {
	log.Println("sl.unlock")
	sl.lock.Unlock()
}

func (sl *SuperLock) StartStream() {
	log.Println("sl.startstream")
	sl.self.Lock()
	defer sl.self.Unlock()

	select {
	case sl.sem <- struct{}{}:
	case <-time.After(time.Second * 3):
		log.Println("timed out getting semaphore to start stream")
		return
	}

	log.Println("CONT STREAM", len(sl.sem))
	startStream()
}

func (sl *SuperLock) StopStream() {
	log.Println("sl.stopstream")
	sl.self.Lock()
	defer sl.self.Unlock()

	select {
	case <-sl.sem:
	case <-time.After(time.Second * 3):
		log.Println("timed out getting semaphore to stop stream")
		return
	}

	log.Println("STOP STREAM", len(sl.sem))
	if len(sl.sem) > 0 {
		return
	}

	log.Println("REALLY DO STOP STREAM", len(sl.sem))
	stopStream()
}
