/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to you 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 avatica provides an Apache Phoenix Query Server/Avatica driver for Go's database/sql package.

# Quickstart

Import the database/sql package along with the avatica driver.

	import "database/sql"
	import _ "github.com/apache/calcite-avatica-go/v5"

	db, err := sql.Open("avatica", "http://phoenix-query-server:8765")

See https://calcite.apache.org/avatica/docs/go_client_reference.html for more details
*/
package avatica

import (
	"context"
	"database/sql"
	"database/sql/driver"
	"fmt"
	"net/http"

	"github.com/apache/calcite-avatica-go/v5/generic"
	"github.com/apache/calcite-avatica-go/v5/hsqldb"
	"github.com/apache/calcite-avatica-go/v5/message"
	"github.com/apache/calcite-avatica-go/v5/phoenix"
	"github.com/hashicorp/go-uuid"
)

// Driver is exported to allow it to be used directly.
type Driver struct{}

// Connector implements the driver.Connector interface
type Connector struct {
	Info   map[string]string
	Client *http.Client

	dsn string
}

// NewConnector creates a new connector
func NewConnector(dsn string) driver.Connector {
	return &Connector{
		Info: make(map[string]string),
		dsn:  dsn,
	}
}

func (c *Connector) Connect(context.Context) (driver.Conn, error) {

	config, err := ParseDSN(c.dsn)

	if err != nil {
		return nil, fmt.Errorf("unable to open connection: %w", err)
	}

	// propagate user and password to connector info so that it's available in JDBC context for example
	if config.avaticaUser != "" {
		c.Info["user"] = config.avaticaUser
	}
	if config.avaticaPassword != "" {
		c.Info["password"] = config.avaticaPassword
	}

	connectionId, err := uuid.GenerateUUID()
	if err != nil {
		return nil, fmt.Errorf("error generating connection id: %w", err)
	}
	httpClient, err := NewHTTPClient(config.endpoint, c.Client, config)

	if err != nil {
		return nil, fmt.Errorf("unable to create HTTP client: %w", err)
	}
	conn := &conn{
		connectionId:  connectionId,
		httpClient:    httpClient,
		config:        config,
		connectorInfo: c.Info,
	}
	err = registerConn(conn)
	if err != nil {
		return nil, err
	}
	response, err := conn.httpClient.post(context.Background(), &message.DatabasePropertyRequest{
		ConnectionId: conn.connectionId,
	})

	if err != nil {
		return nil, conn.avaticaErrorToResponseErrorOrError(err)
	}

	databasePropertyResponse := response.(*message.DatabasePropertyResponse)

	adapter := ""

	for _, property := range databasePropertyResponse.Props {
		if property.Key.Name == "GET_DRIVER_NAME" {
			adapter = property.Value.StringValue
		}
	}

	conn.adapter = getAdapter(adapter)

	return conn, nil
}

func registerConn(conn *conn) error {
	info := map[string]string{
		"AutoCommit":  "true",
		"Consistency": "8",
	}
	for k, v := range conn.connectorInfo {
		info[k] = v
	}
	// Open a connection to the server
	req := &message.OpenConnectionRequest{
		ConnectionId: conn.connectionId,
		Info:         info,
	}
	if conn.config.schema != "" {
		req.Info["schema"] = conn.config.schema
	}
	_, err := conn.httpClient.post(context.Background(), req)
	if err != nil {
		return conn.avaticaErrorToResponseErrorOrError(err)
	}
	return nil
}

// Driver returns the underlying driver
func (c *Connector) Driver() driver.Driver {
	return &Driver{}
}

// Open a Connection to the server.
// See https://github.com/apache/calcite-avatica-go#dsn for more information
// on how the DSN is formatted.
func (a *Driver) Open(dsn string) (driver.Conn, error) {
	return NewConnector(dsn).Connect(context.TODO())
}

func getAdapter(e string) Adapter {
	switch e {
	case "HSQL Database Engine Driver":
		return hsqldb.Adapter{}
	case "PhoenixEmbeddedDriver":
		return phoenix.Adapter{}
	default:
		return generic.Adapter{}
	}
}

func init() {
	sql.Register("avatica", &Driver{})
}
