package main

import (
	"flag"
	"log"
	"net/http"
	"time"

	"github.com/gorilla/mux"
	"github.com/pkg/errors"
	bolt "go.etcd.io/bbolt"
)

type ParsedArguments struct {
	databaseName string
}

var appConfig ParsedArguments
var db *bolt.DB

func main() {
	// Parse the arguments and construct the ParsedArguments
	appConfigRef, err := parseArguments()
	if err != nil {
		log.Fatal(err)
	}
	appConfig = *appConfigRef

	// Open the bolt database
	db, err = bolt.Open(appConfig.databaseName, 0666, &bolt.Options{Timeout: 1 * time.Second})
	if err != nil {
		decoratedErr := errors.Wrapf(err, "failed to open database at '%v'", appConfig.databaseName)
		log.Fatal(decoratedErr)
	}
	defer db.Close()
	err = db.Update(migrateDatabase)
	if err != nil {
		decoratedErr := errors.Wrapf(err, "failed to migrate database")
		log.Fatal(decoratedErr)
	}

	// Export prometheus metrics
	go startMetricsServer()

	// Initialize Gorilla router
	router := mux.NewRouter()
	router.HandleFunc("/", indexGetHandler).Methods("GET")
	router.HandleFunc("/", indexPostHandler).Methods("POST")
	router.HandleFunc("/{key:[A-Za-z0-9-_]{4,}}", pasteGetHandler).Methods("GET")
	router.HandleFunc("/{key:[A-Za-z0-9-_]{4,}}/nr", pasteGetHandlerNoRedirect).Methods("GET")
	router.HandleFunc("/{key:[A-Za-z0-9-_]{4,}}/meta", pasteGetHandlerMeta).Methods("GET")

	// Start the server
	srv := &http.Server{
		Handler:      router,
		Addr:         "127.0.0.1:8000",
		WriteTimeout: 15 * time.Second,
		ReadTimeout:  15 * time.Second,
	}
	log.Fatal(srv.ListenAndServe())
}

// Parse the input arguments and return the initialized application config struct
func parseArguments() (*ParsedArguments, error) {
	config := ParsedArguments{}

	flag.StringVar(&config.databaseName, "database", "", "Location of the database file")
	flag.Parse()

	if config.databaseName == "" {
		return nil, errors.New("database not set")
	}
	return &config, nil
}