/**************************************************************************************
 *
 *     Project:    General use
 *     File name:  configPoller.go
 *     Version:    1.0.0
 *     Date:       2017-08-19
 *
 *     Autor:      Bogdanovic Theodor
 *     Contact:    t.bogdanovic@hotmail.com
 *
 *     License:    GPLv3
 *
 **************************************************************************************/
/**************************************************************************************
 * Copyright 2018 Bogdanovic Theodor
 *
 * This file is part of configPoller.
 *
 * configPoller is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * configPoller is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with configPoller.  If not, see <http://www.gnu.org/licenses/>.
 **************************************************************************************/
/**************************************************************************************
 *  Further explanations:  This source code is under the license specified by the
 *                         Autor above. Core components or other packages are still
 *                         in source code form, under the license specified by the
 *                         respective author.
 **************************************************************************************/

// Package configPoller takes one ore more configMap per instance
// and start a gouroutine that check in a fix interval if the config file
// has changed
package configPoller

import (
	"time"
)

//*****************************************************************************
//*
//*      Structure: confgReaderContainer
//*
//*****************************************************************************

// confgReaderContainer is the structure containing the
// configReader and the CheckSum of the config files
type confgReaderContainer struct {
	confReader IUpdateConfig
	checksum   [16]byte
}

//*****************************************************************************
//*
//*      Structure: configPoller
//*
//*****************************************************************************

// ConfigPoller contains a slice of various configReaders
// isLocked regulates that always the same instance is
// sent back after the creation (Singelton Pattern)
type configPoller struct {
	readers []*confgReaderContainer

	// Interval in seconds
	interval int
}

/********************* Methods ************************************************/

// observeChanges is executed in a separate goroutine
// and checks after specified time whether config files were changed
func (slf *configPoller) observeChanges() {

	for {
		for _, reader := range slf.readers {
			newChkSum := reader.confReader.GetMd5Sum()
			if reader.checksum != newChkSum {
				reader.confReader.UpdateConfig()
				reader.checksum = newChkSum
			}
		}
		time.Sleep(time.Second * time.Duration(slf.interval))
	}
}

//*****************************************************************************
//*
//*      Public Functions
//*
//*****************************************************************************

// RegisterReaders accepts one or more configReaders and stores
// them in the structure configPoller, which is then executed by
// method observeChanges() in a separate goroutine
func RegisterReaders(intVal int, readers ...IUpdateConfig) {

	if len(readers) == 0 {
		panic("No list of configReaders has been defined!")
	}

	var cp configPoller

	for _, reader := range readers {
		crc := &confgReaderContainer{
			confReader: reader,
		}
		crc.checksum = crc.confReader.GetMd5Sum()
		cp.readers = append(cp.readers, crc)
	}
	cp.interval = intVal

	// Starts the poller in a separate goroutine
	go cp.observeChanges()
}
