// counter
package main

import (
	"sync"
	"time"
)

type Counterchan struct {
	tipo string
	val  int
}

// Counter structure
type Counter struct {
	mu     sync.Mutex
	user   int
	log    int
	insert int
	rem    int
	err    int
	dup    int
	time   time.Duration
	wg     int
}

// NewCounter iniitialized Counter structure
func NewCounter() *Counter {
	return &Counter{
		user:   0,
		log:    0,
		insert: 0,
		err:    0,
		rem:    0,
		dup:    0,
		time:   0,
		wg:     0,
	}
}

func (c *Counter) Run() {
	for {
		tocount := <-counter

		switch tocount.tipo {
		case "user":
			c.addUser()
		case "dup":
			c.addDuplicate(tocount.val)
		case "ins":
			c.addInsert(tocount.val)
		case "log":
			c.addLog(tocount.val)
		case "rem":
			c.addRem(tocount.val)
		case "wg":
			if tocount.val > 0 {
				c.addWG()
			} else {
				c.delWG()
			}
		case "err":
			c.addErr(tocount.val)

		}
	}
}

// AddUser increment number of users managed
func (c *Counter) addUser() {
	c.user++
}

// AddDuplicate increment number of duplicates log
func (c *Counter) addDuplicate(add int) {
	c.dup += add
}

// AddInsert increment number of inserted rows
func (c *Counter) addInsert(add int) {
	c.insert += add
}

// AddLog increment number of log's rows managed
func (c *Counter) addLog(add int) {
	c.log += add
}

//AddRem increment removed logs row
func (c *Counter) addRem(add int) {
	c.rem += add
}

// AddWG ...
func (c *Counter) addWG() {
	c.wg++
}

// AddErr ...
func (c *Counter) addErr(add int) {
	c.err += add
}

// DelWG ...
func (c *Counter) delWG() {
	c.wg--
}

// GetUser return total users
func (c *Counter) GetUser() (ret int) {
	c.mu.Lock()
	defer c.mu.Unlock()
	ret = c.user
	return
}

// GetDup return total duplicated logins
func (c *Counter) GetDup() (ret int) {
	c.mu.Lock()
	defer c.mu.Unlock()
	ret = c.dup
	return
}

// GetLog return total log's rows
func (c *Counter) GetLog() (ret int) {
	c.mu.Lock()
	defer c.mu.Unlock()
	ret = c.log
	return
}

// GetInsert return total inserted rows
func (c *Counter) GetInsert() (ret int) {
	c.mu.Lock()
	defer c.mu.Unlock()
	ret = c.insert
	return
}

// GetErr return total errors
func (c *Counter) GetErr() (ret int) {
	c.mu.Lock()
	defer c.mu.Unlock()
	ret = c.err
	return
}

// GetRem return total removed log's rows
func (c *Counter) GetRem() (ret int) {
	c.mu.Lock()
	defer c.mu.Unlock()
	ret = c.rem
	return
}

// GetWG ...
func (c *Counter) GetWG() (ret int) {
	c.mu.Lock()
	defer c.mu.Unlock()
	ret = c.wg
	return
}

// GetTime ...
func (c *Counter) GetTime() (ret float64) {
	c.mu.Lock()
	defer c.mu.Unlock()
	ret = c.time.Seconds()
	return
}

// SetTime ...
func (c *Counter) SetTime(t time.Duration) {
	c.mu.Lock()
	defer c.mu.Unlock()
	c.time = t
}