/*

 * tracker | MatterLinux package tracker
 * MatterLinux 2023-2024 (https://matterlinux.xyz)

 * This program 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.

 * This program 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 this program.  If not, see <https://www.gnu.org/licenses/>.

 */

package main

import (
	"time"

	"git.matterlinux.xyz/matter/tracker/lib"
	"git.matterlinux.xyz/matter/tracker/log"
	"git.matterlinux.xyz/matter/tracker/routes"
	"github.com/gofiber/fiber/v2"
	"github.com/gofiber/template/html/v2"
)

type tracker struct {
	Channel chan struct{}
	Config  lib.Config
	Last    time.Time
	List    []lib.Package
	Tick    *time.Ticker
}

func (t *tracker) Reload() error {
	t.List = []lib.Package{}
	t.Last = time.Now()

	for _, p := range t.Config.Pools {
		if err := p.Load(&t.List); err != nil {
			return err
		}
	}

	return nil
}

func (t *tracker) Loop() {
	if err := t.Config.Load(&t.List, "config.json"); err != nil {
		log.Error("Failed to load the configuration: %s", err.Error())
		return
	}

	if err := t.Reload(); err != nil {
		log.Error("Failed to update packages: %s", err.Error())
		return
	}

	t.Tick = time.NewTicker(time.Minute * time.Duration(t.Config.Interval))

	for {
		select {
		case <-t.Tick.C:
			if err := t.Reload(); err != nil {
				log.Error("Failed to update packages: %s", err.Error())
			}

		case <-t.Channel:
			t.Tick.Stop()
			return
		}
	}
}

func (t *tracker) Stop() {
	close(t.Channel)
}

func main() {
	var (
		tracker tracker
		app     *fiber.App
		err     error
	)

	app = fiber.New(fiber.Config{
		DisableStartupMessage: true,
		Views:                 html.New("./templates", ".html"),
	})

	app.Static("/", "./public")

	app.All("*", func(c *fiber.Ctx) error {
		c.Locals("config", &tracker.Config)
		c.Locals("list", &tracker.List)
		c.Locals("last", &tracker.Last)
		return c.Next()
	})

	app.Get("/", routes.GET_index)
	app.Get("/p/:name/:version", routes.GET_package)

	app.Get("*", func(c *fiber.Ctx) error {
		return lib.RenderError(c, 404)
	})

	go tracker.Loop()

	log.Info("Starting MatterLinux package tracker on port 9877")

	if err = app.Listen(":9877"); err != nil {
		log.Error("Error starting server: %s", err.Error())
	}

	tracker.Stop()
}