// Copyright 2016 Google Inc. All Rights Reserved.
//
// 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 translate is a client for the Google Translate API.
// See https://cloud.google.com/translate for details.
//
// This package is experimental and subject to change without notice.
package translate

import (
	"fmt"

	"google.golang.org/api/option"
	"google.golang.org/api/transport"

	raw "cloud.google.com/go/translate/internal/translate/v2"
	"golang.org/x/net/context"
	"golang.org/x/text/language"
)

const userAgent = "gcloud-golang-translate/20161115"

// Scope is the OAuth2 scope required by the Google Cloud Vision API.
const Scope = raw.CloudPlatformScope

// Client is a client for the translate API.
type Client struct {
	raw *raw.Service
}

const prodAddr = "https://translation.googleapis.com/language/translate/"

// NewClient constructs a new Client that can perform Translate operations.
//
// You can find or create API key for your project from the Credentials page of
// the Developers Console (console.developers.google.com).
func NewClient(ctx context.Context, opts ...option.ClientOption) (*Client, error) {
	o := []option.ClientOption{
		option.WithEndpoint(prodAddr),
		option.WithScopes(Scope),
		option.WithUserAgent(userAgent),
	}
	o = append(o, opts...)
	httpClient, endpoint, err := transport.NewHTTPClient(ctx, o...)
	if err != nil {
		return nil, fmt.Errorf("dialing: %v", err)
	}
	rawService, err := raw.New(httpClient)
	if err != nil {
		return nil, fmt.Errorf("translate client: %v", err)
	}
	rawService.BasePath = endpoint
	return &Client{raw: rawService}, nil
}

// Close closes any resources held by the client.
// Close should be called when the client is no longer needed.
// It need not be called at program exit.
func (c *Client) Close() error { return nil }

// Translate one or more strings of text from a source language to a target
// language. All inputs must be in the same language.
//
// The target parameter supplies the language to translate to. The supported
// languages are listed at
// https://cloud.google.com/translate/v2/translate-reference#supported_languages.
// You can also call the SupportedLanguages method.
//
// The returned Translations appear in the same order as the inputs.
func (c *Client) Translate(ctx context.Context, inputs []string, target language.Tag, opts *Options) ([]Translation, error) {
	call := c.raw.Translations.List(inputs, target.String()).Context(ctx)
	if opts != nil {
		if s := opts.Source; s != language.Und {
			call.Source(s.String())
		}
		if f := opts.Format; f != "" {
			call.Format(string(f))
		}
		if m := opts.Model; m != "" {
			call.Model(m)
		}
	}
	res, err := call.Do()
	if err != nil {
		return nil, err
	}
	var ts []Translation
	for _, t := range res.Translations {
		var source language.Tag
		if t.DetectedSourceLanguage != "" {
			source, err = language.Parse(t.DetectedSourceLanguage)
			if err != nil {
				return nil, err
			}
		}
		ts = append(ts, Translation{
			Text:   t.TranslatedText,
			Source: source,
			Model:  t.Model,
		})
	}
	return ts, nil
}

// Options contains options for Translate.
type Options struct {
	// Source is the language of the input strings. If empty, the service will
	// attempt to identify the source language automatically and return it within
	// the response.
	Source language.Tag

	// Format describes the format of the input texts. The choices are HTML or
	// Text. The default is HTML.
	Format Format

	// The model to use for translation. The choices are "nmt" or "base". The
	// default is "base".
	Model string
}

// The format of the input text. Used in Options.Format.
type Format string

// Constants for Options.Format.
const (
	HTML Format = "html"
	Text Format = "text"
)

// A Translation contains the results of translating a piece of text.
type Translation struct {
	// Text is the input text translated into the target language.
	Text string

	// Source is the detected language of the input text, if source was
	// not supplied to Client.Translate. If source was supplied, this field
	// will be empty.
	Source language.Tag

	// Model is the model that was used for translation.
	// It may not match the model provided as an option to Client.Translate.
	Model string
}

// DetectLanguage attempts to determine the language of the inputs. Each input
// string may be in a different language.
//
// Each slice of Detections in the return value corresponds with one input
// string. A slice of Detections holds multiple hypotheses for the language of
// a single input string.
func (c *Client) DetectLanguage(ctx context.Context, inputs []string) ([][]Detection, error) {
	call := c.raw.Detections.List(inputs).Context(ctx)
	res, err := call.Do()
	if err != nil {
		return nil, err
	}
	var result [][]Detection
	for _, raws := range res.Detections {
		var ds []Detection
		for _, rd := range raws {
			tag, err := language.Parse(rd.Language)
			if err != nil {
				return nil, err
			}
			ds = append(ds, Detection{
				Language:   tag,
				Confidence: rd.Confidence,
				IsReliable: rd.IsReliable,
			})
		}
		result = append(result, ds)
	}
	return result, nil
}

// Detection represents information about a language detected in an input.
type Detection struct {
	// Language is the code of the language detected.
	Language language.Tag

	// Confidence is a number from 0 to 1, with higher numbers indicating more
	// confidence in the detection.
	Confidence float64

	// IsReliable indicates whether the language detection result is reliable.
	IsReliable bool
}

// SupportedLanguages returns a list of supported languages for translation.
// The target parameter is the language to use to return localized, human
// readable names of supported languages.
func (c *Client) SupportedLanguages(ctx context.Context, target language.Tag) ([]Language, error) {
	call := c.raw.Languages.List().Context(ctx).Target(target.String())
	res, err := call.Do()
	if err != nil {
		return nil, err
	}
	var ls []Language
	for _, l := range res.Languages {
		tag, err := language.Parse(l.Language)
		if err != nil {
			return nil, err
		}
		ls = append(ls, Language{
			Name: l.Name,
			Tag:  tag,
		})
	}
	return ls, nil
}

// A Language describes a language supported for translation.
type Language struct {
	// Name is the human-readable name of the language.
	Name string

	// Tag is a standard code for the language.
	Tag language.Tag
}
