// Copyright 2016 The LUCI Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package portal

import (
	"context"
	"errors"
	"fmt"
	"html/template"
	"sync"
)

// Page controls how some portal section (usually corresponding to a key in
// global settings JSON blob) is displayed and edited in UI.
//
// Packages that wishes to expose UI for managing their settings register a page
// via RegisterPage(...) call during init() time.
type Page interface {
	// Title is used in UI to name this page.
	Title(c context.Context) (string, error)

	// Overview is optional HTML paragraph describing this page.
	Overview(c context.Context) (template.HTML, error)

	// Fields describes the schema of the settings on the page (if any).
	Fields(c context.Context) ([]Field, error)

	// Actions is additional list of actions to present on the page.
	//
	// Each action is essentially a clickable button that triggers a parameterless
	// callback that either does some state change or (if marked as NoSideEffects)
	// just returns some information that is displayed on a separate page.
	Actions(c context.Context) ([]Action, error)

	// ReadSettings returns a map "field ID => field value to display".
	//
	// It is called when rendering the settings page.
	ReadSettings(c context.Context) (map[string]string, error)

	// WriteSettings saves settings described as a map "field ID => field value".
	//
	// Only values of editable, not read only fields are passed here. All values
	// are also validated using field's validators before this call.
	WriteSettings(c context.Context, values map[string]string, who, why string) error
}

// Field is description of a single UI element of the page.
//
// Its ID acts as a key in map used by ReadSettings\WriteSettings.
type Field struct {
	ID             string             // page unique ID
	Title          string             // human friendly name
	Type           FieldType          // how the field is displayed and behaves
	ReadOnly       bool               // if true, display the field as immutable
	Placeholder    string             // optional placeholder value
	Validator      func(string) error // optional value validation
	Help           template.HTML      // optional help text
	ChoiceVariants []string           // valid only for FieldChoice
}

// FieldType describes look and feel of UI field, see the enum below.
type FieldType string

// Note: exact values here are important. They are referenced in the HTML
// template that renders the settings page. See server/portal/*.
const (
	FieldText     FieldType = "text"     // one line of text, editable
	FieldChoice   FieldType = "choice"   // pick one of predefined choices
	FieldStatic   FieldType = "static"   // one line of text, read only
	FieldPassword FieldType = "password" // one line of text, editable but obscured
)

// IsEditable returns true for fields that can be edited.
func (f *Field) IsEditable() bool {
	return f.Type != FieldStatic && !f.ReadOnly
}

// Action corresponds to a button that triggers a parameterless callback.
type Action struct {
	ID            string        // page-unique ID
	Title         string        // what's displayed on the button
	Help          template.HTML // optional help text
	Confirmation  string        // optional text for "Are you sure?" confirmation prompt
	NoSideEffects bool          // if true, the callback just returns some data

	// Callback is executed on click on the action button.
	//
	// Usually it will execute some state change and return the confirmation text
	// (along with its title). If NoSideEffects is true, it may just fetch and
	// return some data (which is either too big or too costly to fetch on the
	// main page).
	Callback func(c context.Context) (title string, body template.HTML, err error)
}

// BasePage can be embedded into Page implementers to provide default
// behavior.
type BasePage struct{}

// Title is used in UI to name this portal page.
func (BasePage) Title(c context.Context) (string, error) {
	return "Untitled portal page", nil
}

// Overview is optional HTML paragraph describing this portal page.
func (BasePage) Overview(c context.Context) (template.HTML, error) {
	return "", nil
}

// Fields describes the schema of the settings on the page (if any).
func (BasePage) Fields(c context.Context) ([]Field, error) {
	return nil, nil
}

// Actions is additional list of actions to present on the page.
func (BasePage) Actions(c context.Context) ([]Action, error) {
	return nil, nil
}

// ReadSettings returns a map "field ID => field value to display".
func (BasePage) ReadSettings(c context.Context) (map[string]string, error) {
	return nil, nil
}

// WriteSettings saves settings described as a map "field ID => field value".
func (BasePage) WriteSettings(c context.Context, values map[string]string, who, why string) error {
	return errors.New("not implemented")
}

// RegisterPage makes exposes UI for a portal page (identified by given
// unique key).
//
// Should be called once when application starts (e.g. from init() of a package
// that defines the page). Panics if such key is already registered.
func RegisterPage(pageKey string, p Page) {
	registry.registerPage(pageKey, p)
}

// GetPages returns a map with all registered pages.
func GetPages() map[string]Page {
	return registry.getPages()
}

////////////////////////////////////////////////////////////////////////////////
// Internal stuff.

var registry pageRegistry

type pageRegistry struct {
	lock  sync.RWMutex
	pages map[string]Page
}

func (r *pageRegistry) registerPage(pageKey string, p Page) {
	r.lock.Lock()
	defer r.lock.Unlock()
	if r.pages == nil {
		r.pages = make(map[string]Page)
	}
	if existing, _ := r.pages[pageKey]; existing != nil {
		panic(fmt.Errorf("portal page for %s is already registered: %T", pageKey, existing))
	}
	r.pages[pageKey] = p
}

func (r *pageRegistry) getPages() map[string]Page {
	r.lock.RLock()
	defer r.lock.RUnlock()
	cpy := make(map[string]Page, len(r.pages))
	for k, v := range r.pages {
		cpy[k] = v
	}
	return cpy
}
