// Copyright 2018 Drone.IO Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package oauth1

import (
	"net/http"

	"github.com/drone/go-login/login"
)

// Handler returns a Handler that runs h at the completion
// of the oauth2 authorization flow.
func Handler(h http.Handler, c *Config) http.Handler {
	return &handler{next: h, conf: c}
}

type handler struct {
	conf *Config
	next http.Handler
}

func (h *handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()

	verifier := r.FormValue("oauth_verifier")
	if verifier == "" {
		token, err := h.conf.requestToken()
		if err != nil {
			ctx = login.WithError(ctx, err)
			h.next.ServeHTTP(w, r.WithContext(ctx))
			return
		}
		redirectTo, err := h.conf.authorizeRedirect(token.Token)
		if err != nil {
			ctx = login.WithError(ctx, err)
			h.next.ServeHTTP(w, r.WithContext(ctx))
			return
		}
		http.Redirect(w, r, redirectTo, 302)
		return
	}

	token := r.FormValue("oauth_token")

	// requests the access_token from the authorization server.
	// If an error is encountered, write the error to the
	// context and prceed with the next http.Handler in the chain.
	accessToken, err := h.conf.authorizeToken(token, verifier)
	if err != nil {
		ctx = login.WithError(ctx, err)
		h.next.ServeHTTP(w, r.WithContext(ctx))
		return
	}

	// converts the oauth2 token type to the internal Token
	// type and attaches to the context.
	ctx = login.WithToken(ctx, &login.Token{
		Access:  accessToken.Token,
		Refresh: accessToken.TokenSecret,
	})

	h.next.ServeHTTP(w, r.WithContext(ctx))
}
