// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Browspr is the browser version of WSPR, intended to communicate with javascript through postMessage.
package browspr

import (
	"fmt"
	"reflect"
	"sync"

	"v.io/v23"
	"v.io/v23/context"
	"v.io/v23/rpc"
	"v.io/v23/vdl"
	"v.io/v23/vtrace"
	"v.io/x/ref/lib/security"
	"v.io/x/ref/services/wspr/internal/account"
	"v.io/x/ref/services/wspr/internal/app"
	"v.io/x/ref/services/wspr/internal/principal"
)

// Browspr is an intermediary between our javascript code and the vanadium
// network that allows our javascript library to use vanadium.
type Browspr struct {
	ctx              *context.T
	listenSpec       *rpc.ListenSpec
	namespaceRoots   []string
	accountManager   *account.AccountManager
	postMessage      func(instanceId int32, ty, msg string)
	principalManager *principal.PrincipalManager

	mu              sync.Mutex
	activeInstances map[int32]*pipe // GUARDED_BY mu
}

// Create a new Browspr instance.
func NewBrowspr(ctx *context.T,
	postMessage func(instanceId int32, ty, msg string),
	listenSpec *rpc.ListenSpec,
	identd string,
	wsNamespaceRoots []string,
	principalSerializer security.SerializerReaderWriter) *Browspr {
	if listenSpec.Proxy == "" {
		ctx.Fatalf("a vanadium proxy must be set")
	}
	if identd == "" {
		ctx.Fatalf("an identd server must be set")
	}

	browspr := &Browspr{
		listenSpec:      listenSpec,
		namespaceRoots:  wsNamespaceRoots,
		postMessage:     postMessage,
		ctx:             ctx,
		activeInstances: make(map[int32]*pipe),
	}

	// TODO(nlacasse, bjornick) use a serializer that can actually persist.
	var err error
	p := v23.GetPrincipal(ctx)

	if principalSerializer == nil {
		ctx.Fatalf("principalSerializer must not be nil")
	}

	if browspr.principalManager, err = principal.NewPrincipalManager(p, principalSerializer); err != nil {
		ctx.Fatalf("principal.NewPrincipalManager failed: %s", err)
	}

	browspr.accountManager = account.NewAccountManager(identd, browspr.principalManager)

	return browspr
}

func (b *Browspr) Shutdown() {
	// TODO(ataly, bprosnitz): Get rid of this method if possible.
}

// CreateInstance creates a new pipe and stores it in activeInstances map.
func (b *Browspr) createInstance(instanceId int32, origin string, namespaceRoots []string, proxy string) (*pipe, error) {
	b.mu.Lock()
	defer b.mu.Unlock()

	// Make sure we don't already have an instance.
	p, ok := b.activeInstances[instanceId]
	if ok {
		return nil, fmt.Errorf("InstanceId %v already has an open instance.", instanceId)
	}

	p = newPipe(b, instanceId, origin, namespaceRoots, proxy)
	if p == nil {
		return nil, fmt.Errorf("Could not create pipe for instanceId %v and origin %v", instanceId, origin)
	}
	b.activeInstances[instanceId] = p
	return p, nil
}

// HandleMessage handles most messages from javascript and forwards them to a
// Controller.
func (b *Browspr) HandleMessage(instanceId int32, origin string, msg app.Message) error {
	b.mu.Lock()
	p, ok := b.activeInstances[instanceId]
	b.mu.Unlock()
	if !ok {
		return fmt.Errorf("No pipe found for instanceId %v. Must send CreateInstance message first.", instanceId)
	}

	if origin != p.origin {
		return fmt.Errorf("Invalid message origin. InstanceId %v has origin %v, but message is from %v.", instanceId, p.origin, origin)
	}

	return p.handleMessage(msg)
}

// HandleCleanupRpc cleans up the specified instance state. (For instance,
// when a browser tab is closed)
func (b *Browspr) HandleCleanupRpc(val *vdl.Value) (*vdl.Value, error) {
	var msg CleanupMessage
	if err := vdl.Convert(&msg, val); err != nil {
		return nil, fmt.Errorf("HandleCleanupRpc did not receive CleanupMessage, received: %v, %v", val, err)
	}

	b.mu.Lock()

	if pipe, ok := b.activeInstances[msg.InstanceId]; ok {
		// We must unlock the mutex before calling cleanunp, otherwise
		// browspr deadlocks.
		b.mu.Unlock()
		pipe.cleanup(b.ctx)

		b.mu.Lock()
		delete(b.activeInstances, msg.InstanceId)
	}

	b.mu.Unlock()

	return nil, nil
}

// Handler for creating an account in the principal manager.
// A valid OAuth2 access token must be supplied in the request body,
// which is exchanged for blessings from the vanadium blessing server.
// An account based on the blessings is then added to WSPR's principal
// manager, and the set of blessing strings are returned to the client.
func (b *Browspr) HandleAuthCreateAccountRpc(val *vdl.Value) (*vdl.Value, error) {
	var msg CreateAccountMessage
	if err := vdl.Convert(&msg, val); err != nil {
		return nil, fmt.Errorf("HandleAuthCreateAccountRpc did not receive CreateAccountMessage, received: %v, %v", val, err)
	}

	ctx, _ := vtrace.WithNewTrace(b.ctx)
	account, err := b.accountManager.CreateAccount(ctx, msg.Token)
	if err != nil {
		return nil, err
	}

	return vdl.ValueFromReflect(reflect.ValueOf(account))
}

// HandleAssociateAccountMessage associates an account with the specified origin.
func (b *Browspr) HandleAuthAssociateAccountRpc(val *vdl.Value) (*vdl.Value, error) {
	var msg AssociateAccountMessage
	if err := vdl.Convert(&msg, val); err != nil {
		return nil, fmt.Errorf("HandleAuthAssociateAccountRpc did not receive AssociateAccountMessage, received: %v, %v", val, err)
	}
	ctx, _ := vtrace.WithNewTrace(b.ctx)
	if err := b.accountManager.AssociateAccount(ctx, msg.Origin, msg.Account, msg.Caveats); err != nil {
		return nil, err
	}
	return nil, nil
}

// HandleAuthGetAccountsRpc gets the root account name from the account manager.
func (b *Browspr) HandleAuthGetAccountsRpc(*vdl.Value) (*vdl.Value, error) {
	accounts := b.accountManager.GetAccounts()
	return vdl.ValueFromReflect(reflect.ValueOf(accounts))
}

// HandleAuthOriginHasAccountRpc returns true iff the origin has an associated
// principal.
func (b *Browspr) HandleAuthOriginHasAccountRpc(val *vdl.Value) (*vdl.Value, error) {
	var msg OriginHasAccountMessage
	if err := vdl.Convert(&msg, val); err != nil {
		return nil, fmt.Errorf("HandleAuthOriginHasAccountRpc did not receive OriginHasAccountMessage, received: %v, %v", val, err)
	}

	res := b.accountManager.OriginHasAccount(msg.Origin)
	return vdl.ValueFromReflect(reflect.ValueOf(res))
}

// HandleCreateInstanceRpc sets the namespace root and proxy on the pipe, if
// any are provided.
func (b *Browspr) HandleCreateInstanceRpc(val *vdl.Value) (*vdl.Value, error) {
	var msg CreateInstanceMessage
	if err := vdl.Convert(&msg, val); err != nil {
		return nil, fmt.Errorf("HandleCreateInstanceMessage did not receive CreateInstanceMessage, received: %v, %v", val, err)
	}

	_, err := b.createInstance(msg.InstanceId, msg.Origin, msg.NamespaceRoots, msg.Proxy)
	if err != nil {
		return nil, err
	}

	return nil, nil
}
