// Copyright 2016 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 (
	"golang.org/x/net/context"
	bq "google.golang.org/api/bigquery/v2"
)

// CopyConfig holds the configuration for a copy job.
type CopyConfig struct {
	// Srcs are the tables from which data will be copied.
	Srcs []*Table

	// Dst is the table into which the data will be copied.
	Dst *Table

	// CreateDisposition specifies the circumstances under which the destination table will be created.
	// The default is CreateIfNeeded.
	CreateDisposition TableCreateDisposition

	// WriteDisposition specifies how existing data in the destination table is treated.
	// The default is WriteEmpty.
	WriteDisposition TableWriteDisposition

	// The labels associated with this job.
	Labels map[string]string

	// Custom encryption configuration (e.g., Cloud KMS keys).
	DestinationEncryptionConfig *EncryptionConfig
}

func (c *CopyConfig) toBQ() *bq.JobConfiguration {
	var ts []*bq.TableReference
	for _, t := range c.Srcs {
		ts = append(ts, t.toBQ())
	}
	return &bq.JobConfiguration{
		Labels: c.Labels,
		Copy: &bq.JobConfigurationTableCopy{
			CreateDisposition:                  string(c.CreateDisposition),
			WriteDisposition:                   string(c.WriteDisposition),
			DestinationTable:                   c.Dst.toBQ(),
			DestinationEncryptionConfiguration: c.DestinationEncryptionConfig.toBQ(),
			SourceTables:                       ts,
		},
	}
}

func bqToCopyConfig(q *bq.JobConfiguration, c *Client) *CopyConfig {
	cc := &CopyConfig{
		Labels:            q.Labels,
		CreateDisposition: TableCreateDisposition(q.Copy.CreateDisposition),
		WriteDisposition:  TableWriteDisposition(q.Copy.WriteDisposition),
		Dst:               bqToTable(q.Copy.DestinationTable, c),
		DestinationEncryptionConfig: bqToEncryptionConfig(q.Copy.DestinationEncryptionConfiguration),
	}
	for _, t := range q.Copy.SourceTables {
		cc.Srcs = append(cc.Srcs, bqToTable(t, c))
	}
	return cc
}

// A Copier copies data into a BigQuery table from one or more BigQuery tables.
type Copier struct {
	JobIDConfig
	CopyConfig
	c *Client
}

// CopierFrom returns a Copier which can be used to copy data into a
// BigQuery table from one or more BigQuery tables.
// The returned Copier may optionally be further configured before its Run method is called.
func (t *Table) CopierFrom(srcs ...*Table) *Copier {
	return &Copier{
		c: t.c,
		CopyConfig: CopyConfig{
			Srcs: srcs,
			Dst:  t,
		},
	}
}

// Run initiates a copy job.
func (c *Copier) Run(ctx context.Context) (*Job, error) {
	return c.c.insertJob(ctx, c.newJob(), nil)
}

func (c *Copier) newJob() *bq.Job {
	return &bq.Job{
		JobReference:  c.JobIDConfig.createJobRef(c.c),
		Configuration: c.CopyConfig.toBQ(),
	}
}
