/*
 * Copyright Â© 2018-2021 Musing Studio LLC.
 *
 * This file is part of WriteFreely.
 *
 * WriteFreely is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License, included
 * in the LICENSE file in this source code package.
 */

package author

import (
	"github.com/writeas/web-core/log"
	"github.com/writefreely/writefreely/config"
	"os"
	"path/filepath"
	"regexp"
)

// Regex pattern for valid usernames
var validUsernameReg = regexp.MustCompile("^[a-zA-Z0-9][a-zA-Z0-9-]*$")

// List of reserved usernames
var reservedUsernames = map[string]bool{
	"a":                true,
	"about":            true,
	"add":              true,
	"admin":            true,
	"administrator":    true,
	"adminzone":        true,
	"api":              true,
	"article":          true,
	"articles":         true,
	"auth":             true,
	"authenticate":     true,
	"browse":           true,
	"c":                true,
	"categories":       true,
	"category":         true,
	"changes":          true,
	"community":        true,
	"create":           true,
	"css":              true,
	"data":             true,
	"dev":              true,
	"developers":       true,
	"draft":            true,
	"drafts":           true,
	"edit":             true,
	"edits":            true,
	"faq":              true,
	"feed":             true,
	"feedback":         true,
	"guide":            true,
	"guides":           true,
	"help":             true,
	"index":            true,
	"invite":           true,
	"js":               true,
	"login":            true,
	"logout":           true,
	"me":               true,
	"media":            true,
	"meta":             true,
	"metadata":         true,
	"new":              true,
	"news":             true,
	"oauth":            true,
	"post":             true,
	"posts":            true,
	"privacy":          true,
	"publication":      true,
	"publications":     true,
	"publish":          true,
	"random":           true,
	"read":             true,
	"reader":           true,
	"register":         true,
	"remove":           true,
	"signin":           true,
	"signout":          true,
	"signup":           true,
	"start":            true,
	"status":           true,
	"summary":          true,
	"support":          true,
	"tag":              true,
	"tags":             true,
	"team":             true,
	"template":         true,
	"templates":        true,
	"terms":            true,
	"terms-of-service": true,
	"termsofservice":   true,
	"theme":            true,
	"themes":           true,
	"tips":             true,
	"tos":              true,
	"update":           true,
	"updates":          true,
	"user":             true,
	"users":            true,
	"yourname":         true,
}

// IsValidUsername returns true if a given username is neither reserved nor
// of the correct format.
func IsValidUsername(cfg *config.Config, username string) bool {
	// Username has to be above a character limit
	if len(username) < cfg.App.MinUsernameLen {
		return false
	}
	// Username is invalid if page with the same name exists. So traverse
	// available pages, adding them to reservedUsernames map that'll be checked
	// later.
	err := filepath.Walk(filepath.Join(cfg.Server.PagesParentDir, "pages"), func(path string, i os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		reservedUsernames[i.Name()] = true
		return nil
	})
	if err != nil {
		log.Error("[IMPORTANT WARNING]: Could not determine IsValidUsername! %s", err)
		return false
	}

	// Username is invalid if it is reserved!
	if _, reserved := reservedUsernames[username]; reserved {
		return false
	}

	// TODO: use correct regexp function here
	return len(validUsernameReg.FindStringSubmatch(username)) > 0
}
