// Copyright 2019 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 bigquery

import (
	"fmt"

	bq "google.golang.org/api/bigquery/v2"
)

// StandardSQLDataType conveys type information using the Standard SQL type
// system.
type StandardSQLDataType struct {
	// ArrayElementType indicates the type of an array's elements, when the
	// TypeKind is ARRAY.
	ArrayElementType *StandardSQLDataType
	// StructType indicates the struct definition (fields), when the
	// TypeKind is STRUCT.
	StructType *StandardSQLStructType
	// The top-level type of this type definition.
	// Can be any standard SQL data type.  For more information about BigQuery
	// data types, see
	// https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types
	//
	// Additional information is available in the REST documentation:
	// https://cloud.google.com/bigquery/docs/reference/rest/v2/StandardSqlDataType
	TypeKind string
}

func (ssdt *StandardSQLDataType) toBQ() (*bq.StandardSqlDataType, error) {
	if ssdt == nil {
		return nil, nil
	}
	bqdt := &bq.StandardSqlDataType{
		TypeKind: ssdt.TypeKind,
	}
	if ssdt.ArrayElementType != nil {
		dt, err := ssdt.ArrayElementType.toBQ()
		if err != nil {
			return nil, err
		}
		bqdt.ArrayElementType = dt
	}
	if ssdt.StructType != nil {
		dt, err := ssdt.StructType.toBQ()
		if err != nil {
			return nil, err
		}
		bqdt.StructType = dt
	}
	return bqdt, nil
}

func bqToStandardSQLDataType(bqdt *bq.StandardSqlDataType) (*StandardSQLDataType, error) {
	if bqdt == nil {
		return nil, nil
	}
	ssdt := &StandardSQLDataType{
		TypeKind: bqdt.TypeKind,
	}

	if bqdt.ArrayElementType != nil {
		dt, err := bqToStandardSQLDataType(bqdt.ArrayElementType)
		if err != nil {
			return nil, err
		}
		ssdt.ArrayElementType = dt
	}
	if bqdt.StructType != nil {
		st, err := bqToStandardSQLStructType(bqdt.StructType)
		if err != nil {
			return nil, err
		}
		ssdt.StructType = st
	}
	return ssdt, nil
}

// StandardSQLField represents a field using the Standard SQL data type system.
type StandardSQLField struct {
	// The name of this field.  Can be absent for struct fields.
	Name string
	// Data type for the field.
	Type *StandardSQLDataType
}

func (ssf *StandardSQLField) toBQ() (*bq.StandardSqlField, error) {
	if ssf == nil {
		return nil, nil
	}
	bqf := &bq.StandardSqlField{
		Name: ssf.Name,
	}
	if ssf.Type != nil {
		dt, err := ssf.Type.toBQ()
		if err != nil {
			return nil, err
		}
		bqf.Type = dt
	}
	return bqf, nil
}

func bqToStandardSQLField(bqf *bq.StandardSqlField) (*StandardSQLField, error) {
	if bqf == nil {
		return nil, nil
	}
	t, err := bqToStandardSQLDataType(bqf.Type)
	if err != nil {
		return nil, err
	}
	return &StandardSQLField{
		Name: bqf.Name,
		Type: t,
	}, nil
}

// StandardSQLStructType represents a structure type, which is a list of Standard SQL fields.
// For more information, see:
// https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct-type
type StandardSQLStructType struct {
	Fields []*StandardSQLField
}

func (ssst *StandardSQLStructType) toBQ() (*bq.StandardSqlStructType, error) {
	if ssst == nil {
		return nil, nil
	}
	fields, err := standardSQLStructFieldsToBQ(ssst.Fields)
	if err != nil {
		return nil, err
	}
	return &bq.StandardSqlStructType{
		Fields: fields,
	}, nil
}

func bqToStandardSQLStructType(bqst *bq.StandardSqlStructType) (*StandardSQLStructType, error) {
	if bqst == nil {
		return nil, nil
	}
	var fields []*StandardSQLField
	for _, v := range bqst.Fields {
		f, err := bqToStandardSQLField(v)
		if err != nil {
			return nil, err
		}
		fields = append(fields, f)
	}
	return &StandardSQLStructType{
		Fields: fields,
	}, nil
}

func standardSQLStructFieldsToBQ(fields []*StandardSQLField) ([]*bq.StandardSqlField, error) {
	var bqFields []*bq.StandardSqlField
	for _, v := range fields {
		bqf, err := v.toBQ()
		if err != nil {
			return nil, fmt.Errorf("error converting struct fields: %v", err)
		}
		bqFields = append(bqFields, bqf)
	}
	return bqFields, nil
}

// StandardSQLTableType models a table-like resource, which has a set of columns.
type StandardSQLTableType struct {

	// The columns of the table.
	Columns []*StandardSQLField
}

func (sstt *StandardSQLTableType) toBQ() (*bq.StandardSqlTableType, error) {
	if sstt == nil {
		return nil, nil
	}
	out := &bq.StandardSqlTableType{}
	for k, v := range sstt.Columns {
		bq, err := v.toBQ()
		if err != nil {
			return nil, fmt.Errorf("error converting column %d: %v", k, err)
		}
		out.Columns = append(out.Columns, bq)
	}
	return out, nil
}

func bqToStandardSQLTableType(in *bq.StandardSqlTableType) (*StandardSQLTableType, error) {
	if in == nil {
		return nil, nil
	}
	out := &StandardSQLTableType{}
	for k, v := range in.Columns {
		f, err := bqToStandardSQLField(v)
		if err != nil {
			return nil, fmt.Errorf("error converting column %d: %v", k, err)
		}
		out.Columns = append(out.Columns, f)
	}
	return out, nil
}
