/*
Copyright 2017 Google LLC

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 spanner

import (
	"errors"
	"fmt"

	proto3 "github.com/golang/protobuf/ptypes/struct"

	sppb "google.golang.org/genproto/googleapis/spanner/v1"
	"google.golang.org/grpc/codes"
)

// A Statement is a SQL query with named parameters.
//
// A parameter placeholder consists of '@' followed by the parameter name.
// Parameter names consist of any combination of letters, numbers, and
// underscores. Names may be entirely numeric (e.g., "WHERE m.id = @5").
// Parameters may appear anywhere that a literal value is expected. The same
// parameter name may be used more than once.  It is an error to execute a
// statement with unbound parameters. On the other hand, it is allowable to
// bind parameter names that are not used.
//
// See the documentation of the Row type for how Go types are mapped to Cloud
// Spanner types.
type Statement struct {
	SQL    string
	Params map[string]interface{}
}

// NewStatement returns a Statement with the given SQL and an empty Params map.
func NewStatement(sql string) Statement {
	return Statement{SQL: sql, Params: map[string]interface{}{}}
}

// errBindParam returns error for not being able to bind parameter to query request.
func errBindParam(k string, v interface{}, err error) error {
	if err == nil {
		return nil
	}
	se, ok := toSpannerError(err).(*Error)
	if !ok {
		return spannerErrorf(codes.InvalidArgument, "failed to bind query parameter(name: %q, value: %v), error = <%v>", k, v, err)
	}
	se.decorate(fmt.Sprintf("failed to bind query parameter(name: %q, value: %v)", k, v))
	return se
}

var (
	errNilParam = errors.New("use T(nil), not nil")
	errNoType   = errors.New("no type information")
)

// bindParams binds parameters in a Statement to a sppb.ExecuteSqlRequest or sppb.PartitionQueryRequest.
func (s *Statement) bindParams(i interface{}) error {
	params := &proto3.Struct{
		Fields: map[string]*proto3.Value{},
	}
	paramTypes := map[string]*sppb.Type{}
	for k, v := range s.Params {
		if v == nil {
			return errBindParam(k, v, errNilParam)
		}
		val, t, err := encodeValue(v)
		if err != nil {
			return errBindParam(k, v, err)
		}
		if t == nil { // should not happen, because of nil check above
			return errBindParam(k, v, errNoType)
		}
		params.Fields[k] = val
		paramTypes[k] = t
	}

	switch r := i.(type) {
	default:
		return fmt.Errorf("failed to bind query parameter, unexpected request type: %v", r)
	case *sppb.ExecuteSqlRequest:
		r.Params = params
		r.ParamTypes = paramTypes
	case *sppb.PartitionQueryRequest:
		r.Params = params
		r.ParamTypes = paramTypes
	}
	return nil
}
