// 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"
	"fmt"
	"net/http"

	"github.com/julienschmidt/httprouter"

	"go.chromium.org/luci/server/auth/xsrf"
	"go.chromium.org/luci/server/router"
	"go.chromium.org/luci/server/templates"
)

type fieldWithValue struct {
	Field
	Value string
}

type validationError struct {
	FieldTitle string
	Value      string
	Error      string
}

type pageCallback func(id string, p Page) error

func withPage(c context.Context, rw http.ResponseWriter, p httprouter.Params, cb pageCallback) {
	id := p.ByName("PageKey")
	page := GetPages()[id]
	if page == nil {
		rw.WriteHeader(http.StatusNotFound)
		templates.MustRender(c, rw, "pages/error.html", templates.Args{
			"Error": "No such portal page",
		})
		return
	}
	if err := cb(id, page); err != nil {
		replyError(c, rw, err)
	}
}

func portalPageGET(ctx *router.Context) {
	c, rw, p := ctx.Request.Context(), ctx.Writer, ctx.Params

	withPage(c, rw, p, func(id string, page Page) error {
		title, err := page.Title(c)
		if err != nil {
			return err
		}
		overview, err := page.Overview(c)
		if err != nil {
			return err
		}
		fields, err := page.Fields(c)
		if err != nil {
			return err
		}
		actions, err := page.Actions(c)
		if err != nil {
			return err
		}
		values, err := page.ReadSettings(c)
		if err != nil {
			return err
		}

		withValues := make([]fieldWithValue, len(fields))
		hasEditable := false
		for i, f := range fields {
			withValues[i] = fieldWithValue{
				Field: f,
				Value: values[f.ID],
			}
			hasEditable = hasEditable || f.IsEditable()
		}

		templates.MustRender(c, rw, "pages/page.html", templates.Args{
			"ID":             id,
			"Title":          title,
			"Overview":       overview,
			"Fields":         withValues,
			"Actions":        actions,
			"XsrfTokenField": xsrf.TokenField(c),
			"ShowSaveButton": hasEditable,
		})
		return nil
	})
}

func portalPagePOST(ctx *router.Context) {
	c, rw, r, p := ctx.Request.Context(), ctx.Writer, ctx.Request, ctx.Params

	withPage(c, rw, p, func(id string, page Page) error {
		title, err := page.Title(c)
		if err != nil {
			return err
		}
		fields, err := page.Fields(c)
		if err != nil {
			return err
		}

		// Extract values from the page and validate them.
		values := make(map[string]string, len(fields))
		validationErrors := []validationError{}
		for _, f := range fields {
			if !f.IsEditable() {
				continue
			}
			val := r.PostFormValue(f.ID)
			values[f.ID] = val
			if f.Validator != nil {
				if err := f.Validator(val); err != nil {
					validationErrors = append(validationErrors, validationError{
						FieldTitle: f.Title,
						Value:      val,
						Error:      err.Error(),
					})
				}
			}
		}
		if len(validationErrors) != 0 {
			rw.WriteHeader(http.StatusBadRequest)
			templates.MustRender(c, rw, "pages/validation_error.html", templates.Args{
				"ID":     id,
				"Title":  title,
				"Errors": validationErrors,
			})
			return nil
		}

		// Store.
		err = page.WriteSettings(c, values)
		if err != nil {
			return err
		}
		templates.MustRender(c, rw, "pages/done.html", templates.Args{
			"ID":    id,
			"Title": title,
		})
		return nil
	})
}

func portalActionGETPOST(ctx *router.Context) {
	c, rw, p := ctx.Request.Context(), ctx.Writer, ctx.Params
	actionID := p.ByName("ActionID")

	withPage(c, rw, p, func(id string, page Page) error {
		title, err := page.Title(c)
		if err != nil {
			return err
		}
		actions, err := page.Actions(c)
		if err != nil {
			return err
		}

		var action *Action
		for i := range actions {
			if actions[i].ID == actionID {
				action = &actions[i]
				break
			}
		}
		if action == nil {
			rw.WriteHeader(http.StatusNotFound)
			templates.MustRender(c, rw, "pages/error.html", templates.Args{
				"Error": "No such action defined",
			})
			return nil
		}

		// Make sure side effect free actions are always executed through GET, and
		// ones with side effects are through POST. This is important, since only
		// POST route is protected with XSRF check.
		expectedMethod := "POST"
		if action.NoSideEffects {
			expectedMethod = "GET"
		}
		if ctx.Request.Method != expectedMethod {
			rw.WriteHeader(http.StatusBadRequest)
			templates.MustRender(c, rw, "pages/error.html", templates.Args{
				"Error": fmt.Sprintf("Expecting HTTP method %s, but got %s.", expectedMethod, ctx.Request.Method),
			})
			return nil
		}

		resultTitle, result, err := action.Callback(c)
		if err != nil {
			rw.WriteHeader(http.StatusInternalServerError)
			templates.MustRender(c, rw, "pages/error.html", templates.Args{
				"Error": err.Error(),
			})
			return nil
		}

		templates.MustRender(c, rw, "pages/action_done.html", templates.Args{
			"ID":          id,
			"Title":       title,
			"ResultTitle": resultTitle,
			"Result":      result,
		})
		return nil
	})
}
