package apidAnalytics

import (
	"io/ioutil"
	"os"
	"path/filepath"
	"time"
)

const (
	maxRetries              = 3
	retryFailedDirBatchSize = 10
)

// Each file upload is retried maxRetries times before
// moving it to failed directory
var retriesMap map[string]int

//TODO:  make sure that this instance gets initialized only once
// since we dont want multiple upload manager tickers running
func initUploadManager() {

	retriesMap = make(map[string]int)

	go func() {
		// Periodically check the staging directory to check
		// if any folders are ready to be uploaded to S3
		ticker := time.NewTicker(time.Second *
			config.GetDuration(analyticsUploadInterval))
		log.Debugf("Intialized upload manager to check for staging directory")
		// Ticker will keep running till go routine is running
		// i.e. till application is running
		defer ticker.Stop()

		for range ticker.C {
			files, err := ioutil.ReadDir(localAnalyticsStagingDir)

			if err != nil {
				log.Errorf("Cannot read directory: "+
					"%s", localAnalyticsStagingDir)
			}

			uploadedDirCnt := 0
			for _, file := range files {
				if file.IsDir() {
					status := uploadDir(file)
					handleUploadDirStatus(file, status)
					if status {
						uploadedDirCnt++
					}
				}
			}
			if uploadedDirCnt > 0 {
				// After a successful upload, retry the
				// folders in failed directory as they might have
				// failed due to intermitent S3/GCS issue
				retryFailedUploads()
			}
		}
	}()
}

func handleUploadDirStatus(dir os.FileInfo, status bool) {
	completePath := filepath.Join(localAnalyticsStagingDir, dir.Name())
	// If upload is successful then delete files
	// and remove bucket from retry map
	if status {
		os.RemoveAll(completePath)
		log.Debugf("deleted directory after "+
			"successful upload: %s", dir.Name())
		// remove key if exists from retry map after a successful upload
		delete(retriesMap, dir.Name())
	} else {
		retriesMap[dir.Name()] = retriesMap[dir.Name()] + 1
		if retriesMap[dir.Name()] >= maxRetries {
			log.Errorf("Max Retires exceeded for folder: %s", completePath)
			failedDirPath := filepath.Join(localAnalyticsFailedDir, dir.Name())
			err := os.Rename(completePath, failedDirPath)
			if err != nil {
				log.Errorf("Cannot move directory '%s'"+
					" from staging to failed folder", dir.Name())
			}
			// remove key from retry map once it reaches allowed max failed attempts
			delete(retriesMap, dir.Name())
		}
	}
}

func retryFailedUploads() {
	failedDirs, err := ioutil.ReadDir(localAnalyticsFailedDir)

	if err != nil {
		log.Errorf("Cannot read directory: %s", localAnalyticsFailedDir)
	}

	cnt := 0
	for _, dir := range failedDirs {
		// We rety failed folder in batches to not overload the upload thread
		if cnt < retryFailedDirBatchSize {
			failedPath := filepath.Join(localAnalyticsFailedDir, dir.Name())
			newStagingPath := filepath.Join(localAnalyticsStagingDir, dir.Name())
			err := os.Rename(failedPath, newStagingPath)
			if err != nil {
				log.Errorf("Cannot move directory '%s'"+
					" from failed to staging folder", dir.Name())
			}
			cnt++
		} else {
			break
		}
	}
}
