package lib

import (
	"log"
	"os"
	"strings"
	"time"
)

func getConfig() Config {
	return Config{
		WikiBaseURL:           os.Getenv("WIKI_BASE_URL"),
		WikiToken:             os.Getenv("WIKI_TOKEN"),
		WikiContentLimit:      envToInteger("WIKI_CONTENT_LIMIT", 10),
		WikiDiscordWebhook:    os.Getenv("WIKI_DISCORD_WEBHOOK"),
		RedmineBaseURL:        os.Getenv("REDMINE_BASE_URL"),
		RedmineKey:            os.Getenv("REDMINE_KEY"),
		RedmineContentLimit:   envToInteger("REDMINE_CONTENT_LIMIT", 10),
		RedmineDiscordWebhook: os.Getenv("REDMINE_DISCORD_WEBHOOK"),
		GiteaToken:            os.Getenv("GITEA_TOKEN"),
		GiteaBaseURL:          os.Getenv("GITEA_BASE_URL"),
		GiteaRepos:            strings.Split(os.Getenv("GITEA_REPOS"), ","),
		GiteaContentLimit:     envToInteger("GITEA_CONTENT_LIMIT", 10),
		GiteaDiscordWebhook:   os.Getenv("GITEA_DISCORD_WEBHOOK"),
		GravBaseURL:           os.Getenv("GRAV_BASE_URL"),
		GravContentLimit:      envToInteger("GRAV_CONTENT_LIMIT", 10),
		GravDiscordWebhook:    os.Getenv("GRAV_DISCORD_WEBHOOK"),
		DiscordWebhook:        os.Getenv("DISCORD_WEBHOOK"),
		DiscordFake:           os.Getenv("DISCORD_FAKE") == "true",
		Interval:              time.Duration(envToInteger("INTERVAL_MINUTES", 5)) * time.Minute,
	}
}

func getFetchers(config *Config, cache *Cache) []Fetcher {
	return []Fetcher{
		&GiteaFetcher{
			BaseFetcher: BaseFetcher{
				BaseURL:      config.GiteaBaseURL,
				Token:        config.GiteaToken,
				Cache:        cache,
				ContentLimit: config.GiteaContentLimit,
			},
			Repos: config.GiteaRepos,
		},
		&WikiFetcher{
			BaseFetcher: BaseFetcher{
				BaseURL:      config.WikiBaseURL,
				Token:        config.WikiToken,
				Cache:        cache,
				ContentLimit: config.WikiContentLimit,
			},
		},
		&RedmineFetcher{
			BaseFetcher: BaseFetcher{
				BaseURL:      config.RedmineBaseURL,
				Token:        config.RedmineKey,
				Cache:        cache,
				ContentLimit: config.RedmineContentLimit,
			},
		},
		&GravFetcher{
			BaseFetcher: BaseFetcher{
				BaseURL:      config.GravBaseURL,
				Cache:        cache,
				ContentLimit: config.GravContentLimit,
			},
		},
	}
}

func getCache() Cache {
	cache := *NewCache()
	cache.Load()
	return cache
}

func getMessages(fetchers []Fetcher) []Message {
	messages := []Message{}
	for _, fetcher := range fetchers {
		fetchedMessages := fetcher.Fetch()
		for _, message := range fetchedMessages {
			messages = append(messages, message)
		}
	}
	return messages
}

func sendMessageToDiscord(sender DiscordSender, message Message) {
	log.Printf("[SCHEDULED] [SEND] (%s) %s\n", message.Channel, message.ToDiscord())
	if sender.Fake {
		return
	}
	sender.Send(message.ToDiscord())
}

func Runner() {
	loadEnv()
	config := getConfig()
	cache := getCache()
	fetchers := getFetchers(&config, &cache)

	default_discord_sender := NewDiscordSender(config.DiscordWebhook, config.DiscordFake)
	wiki_discord_sender := NewDiscordSender(config.WikiDiscordWebhook, config.DiscordFake)
	redmine_discord_sender := NewDiscordSender(config.RedmineDiscordWebhook, config.DiscordFake)
	gita_discord_sender := NewDiscordSender(config.GiteaDiscordWebhook, config.DiscordFake)
	grav_discord_sender := NewDiscordSender(config.GravDiscordWebhook, config.DiscordFake)
	for {
		log.Println("[SCHEDULED] Run updater...")
		messages := getMessages(fetchers)
		for _, message := range messages {
			switch message.Channel {
			case "wiki":
				sendMessageToDiscord(wiki_discord_sender, message)
			case "redmine":
				sendMessageToDiscord(redmine_discord_sender, message)
			case "gitea":
				sendMessageToDiscord(gita_discord_sender, message)
			case "grav":
				sendMessageToDiscord(grav_discord_sender, message)
			default:
				sendMessageToDiscord(default_discord_sender, message)
			}
		}
		cache.Save()
		time.Sleep(config.Interval)
	}
}
