package monitor

import (
	
	
	
	

	
	
	
	
	
	
)

type stats struct {
	PID statsPID `json:"pid"`
	OS  statsOS  `json:"os"`
}

type statsPID struct {
	CPU   float64 `json:"cpu"`
	RAM   uint64  `json:"ram"`
	Conns int     `json:"conns"`
}

type statsOS struct {
	CPU      float64 `json:"cpu"`
	RAM      uint64  `json:"ram"`
	TotalRAM uint64  `json:"total_ram"`
	LoadAvg  float64 `json:"load_avg"`
	Conns    int     `json:"conns"`
}

var (
	monitPIDCPU   atomic.Value
	monitPIDRAM   atomic.Value
	monitPIDConns atomic.Value

	monitOSCPU      atomic.Value
	monitOSRAM      atomic.Value
	monitOSTotalRAM atomic.Value
	monitOSLoadAvg  atomic.Value
	monitOSConns    atomic.Value
)

var (
	mutex sync.RWMutex
	once  sync.Once
	data  = &stats{}
)

// New creates a new middleware handler
func ( ...Config) fiber.Handler {
	// Set default config
	 := configDefault(...)

	// Start routine to update statistics
	once.Do(func() {
		,  := process.NewProcess(int32(os.Getpid())) //nolint:errcheck // TODO: Handle error

		updateStatistics()

		go func() {
			for {
				time.Sleep(.Refresh)

				updateStatistics()
			}
		}()
	})

	// Return new handler
	//nolint:errcheck // Ignore the type-assertion errors
	return func( *fiber.Ctx) error {
		// Don't execute middleware if Next returns true
		if .Next != nil && .Next() {
			return .Next()
		}

		if .Method() != fiber.MethodGet {
			return fiber.ErrMethodNotAllowed
		}
		if .Get(fiber.HeaderAccept) == fiber.MIMEApplicationJSON || .APIOnly {
			mutex.Lock()
			data.PID.CPU, _ = monitPIDCPU.Load().(float64)
			data.PID.RAM, _ = monitPIDRAM.Load().(uint64)
			data.PID.Conns, _ = monitPIDConns.Load().(int)

			data.OS.CPU, _ = monitOSCPU.Load().(float64)
			data.OS.RAM, _ = monitOSRAM.Load().(uint64)
			data.OS.TotalRAM, _ = monitOSTotalRAM.Load().(uint64)
			data.OS.LoadAvg, _ = monitOSLoadAvg.Load().(float64)
			data.OS.Conns, _ = monitOSConns.Load().(int)
			mutex.Unlock()
			return .Status(fiber.StatusOK).JSON(data)
		}
		.Set(fiber.HeaderContentType, fiber.MIMETextHTMLCharsetUTF8)
		return .Status(fiber.StatusOK).SendString(.index)
	}
}

func updateStatistics( *process.Process) {
	,  := .CPUPercent()
	if  == nil {
		monitPIDCPU.Store( / 10)
	}

	if ,  := cpu.Percent(0, false);  == nil && len() > 0 {
		monitOSCPU.Store([0])
	}

	if ,  := .MemoryInfo();  == nil &&  != nil {
		monitPIDRAM.Store(.RSS)
	}

	if ,  := mem.VirtualMemory();  == nil &&  != nil {
		monitOSRAM.Store(.Used)
		monitOSTotalRAM.Store(.Total)
	}

	if ,  := load.Avg();  == nil &&  != nil {
		monitOSLoadAvg.Store(.Load1)
	}

	,  := net.ConnectionsPid("tcp", .Pid)
	if  == nil {
		monitPIDConns.Store(len())
	}

	,  := net.Connections("tcp")
	if  == nil {
		monitOSConns.Store(len())
	}
}