// Copyright (C) MongoDB, Inc. 2017-present.
//
// 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

package command

import (
	"context"
	"runtime"

	"github.com/mongodb/mongo-go-driver/version"
	"github.com/mongodb/mongo-go-driver/x/bsonx"
	"github.com/mongodb/mongo-go-driver/x/network/address"
	"github.com/mongodb/mongo-go-driver/x/network/description"
	"github.com/mongodb/mongo-go-driver/x/network/result"
	"github.com/mongodb/mongo-go-driver/x/network/wiremessage"
)

// Handshake represents a generic MongoDB Handshake. It calls isMaster and
// buildInfo.
//
// The isMaster and buildInfo commands are used to build a server description.
type Handshake struct {
	Client             bsonx.Doc
	Compressors        []string
	SaslSupportedMechs string

	ismstr result.IsMaster
	err    error
}

// Encode will encode the handshake commands into a wire message containing isMaster
func (h *Handshake) Encode() (wiremessage.WireMessage, error) {
	var wm wiremessage.WireMessage
	ismstr, err := (&IsMaster{
		Client:             h.Client,
		Compressors:        h.Compressors,
		SaslSupportedMechs: h.SaslSupportedMechs,
	}).Encode()
	if err != nil {
		return wm, err
	}

	wm = ismstr
	return wm, nil
}

// Decode will decode the wire messages.
// Errors during decoding are deferred until either the Result or Err methods
// are called.
func (h *Handshake) Decode(wm wiremessage.WireMessage) *Handshake {
	h.ismstr, h.err = (&IsMaster{}).Decode(wm).Result()
	if h.err != nil {
		return h
	}
	return h
}

// Result returns the result of decoded wire messages.
func (h *Handshake) Result(addr address.Address) (description.Server, error) {
	if h.err != nil {
		return description.Server{}, h.err
	}
	return description.NewServer(addr, h.ismstr), nil
}

// Err returns the error set on this Handshake.
func (h *Handshake) Err() error { return h.err }

// Handshake implements the connection.Handshaker interface. It is identical
// to the RoundTrip methods on other types in this package. It will execute
// the isMaster command.
func (h *Handshake) Handshake(ctx context.Context, addr address.Address, rw wiremessage.ReadWriter) (description.Server, error) {
	wm, err := h.Encode()
	if err != nil {
		return description.Server{}, err
	}

	err = rw.WriteWireMessage(ctx, wm)
	if err != nil {
		return description.Server{}, err
	}

	wm, err = rw.ReadWireMessage(ctx)
	if err != nil {
		return description.Server{}, err
	}
	return h.Decode(wm).Result(addr)
}

// ClientDoc creates a client information document for use in an isMaster
// command.
func ClientDoc(app string) bsonx.Doc {
	doc := bsonx.Doc{
		{"driver",
			bsonx.Document(bsonx.Doc{
				{"name", bsonx.String("mongo-go-driver")},
				{"version", bsonx.String(version.Driver)},
			}),
		},
		{"os",
			bsonx.Document(bsonx.Doc{
				{"type", bsonx.String(runtime.GOOS)},
				{"architecture", bsonx.String(runtime.GOARCH)},
			}),
		},
		{"platform", bsonx.String(runtime.Version())},
	}

	if app != "" {
		doc = append(doc, bsonx.Elem{"application", bsonx.Document(bsonx.Doc{{"name", bsonx.String(app)}})})
	}

	return doc
}
