// Copyright (c) 2016 VMware, Inc. All Rights Reserved.
//
// This product is licensed to you under the Apache License, Version 2.0 (the "License").
// You may not use this product except in compliance with the License.
//
// This product may include a number of subcomponents with separate copyright notices and
// license terms. Your use of these subcomponents is subject to the terms and conditions
// of the subcomponent's license, as noted in the LICENSE file.

package photon

import (
	"crypto/tls"
	"crypto/x509"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
	"time"
)

// Represents stateless context needed to call photon APIs.
type Client struct {
	options           ClientOptions
	restClient        *restClient
	logger            *log.Logger
	Endpoint          string
	Status            *StatusAPI
	Tenants           *TenantsAPI
	Tasks             *TasksAPI
	Projects          *ProjectsAPI
	Flavors           *FlavorsAPI
	Images            *ImagesAPI
	Disks             *DisksAPI
	VMs               *VmAPI
	Hosts             *HostsAPI
	Deployments       *DeploymentsAPI
	ResourceTickets   *ResourceTicketsAPI
	Networks          *NetworksAPI
	Services          *ServicesAPI
	Auth              *AuthAPI
	AvailabilityZones *AvailabilityZonesAPI
	Info              *InfoAPI
	Routers           *RoutersAPI
	Subnets           *SubnetsAPI
	System            *SystemAPI
	Zones             *ZonesAPI
	Infra             *InfraAPI
	InfraHosts        *InfraHostsAPI
}

// Represents Tokens
type TokenOptions struct {
	AccessToken  string `json:"access_token"`
	ExpiresIn    int    `json:"expires_in"`
	RefreshToken string `json:"refresh_token,omitempty"`
	IdToken      string `json:"id_token"`
	TokenType    string `json:"token_type"`
}

type TokenCallback func(string)

// Options for Client
type ClientOptions struct {
	// When using the Tasks.Wait APIs, defines the duration of how long
	// the SDK should continue to poll the server. Default is 30 minutes.
	// TasksAPI.WaitTimeout() can be used to specify timeout on
	// individual calls.
	TaskPollTimeout time.Duration

	// Whether or not to ignore any TLS errors when talking to photon,
	// false by default.
	IgnoreCertificate bool

	// List of root CA's to use for server validation
	// nil by default.
	RootCAs *x509.CertPool

	// For tasks APIs, defines the delay between each polling attempt.
	// Default is 100 milliseconds.
	TaskPollDelay time.Duration

	// For tasks APIs, defines the number of retries to make in the event
	// of an error. Default is 3.
	TaskRetryCount int

	// Tokens for user authentication. Default is empty.
	TokenOptions *TokenOptions

	// A function to be called if the access token was refreshed
	// The client can save the new access token for future API
	// calls so that it doesn't need to be refreshed again.
	UpdateAccessTokenCallback TokenCallback
}

// Creates a new photon client with specified options. If options
// is nil, default options will be used.
func NewClient(endpoint string, options *ClientOptions, logger *log.Logger) (c *Client) {
	defaultOptions := &ClientOptions{
		TaskPollTimeout:   30 * time.Minute,
		TaskPollDelay:     100 * time.Millisecond,
		TaskRetryCount:    3,
		TokenOptions:      &TokenOptions{},
		IgnoreCertificate: false,
		RootCAs:           nil,
	}

	if options != nil {
		if options.TaskPollTimeout != 0 {
			defaultOptions.TaskPollTimeout = options.TaskPollTimeout
		}
		if options.TaskPollDelay != 0 {
			defaultOptions.TaskPollDelay = options.TaskPollDelay
		}
		if options.TaskRetryCount != 0 {
			defaultOptions.TaskRetryCount = options.TaskRetryCount
		}
		if options.TokenOptions != nil {
			defaultOptions.TokenOptions = options.TokenOptions
		}
		if options.RootCAs != nil {
			defaultOptions.RootCAs = options.RootCAs
		}
		defaultOptions.IgnoreCertificate = options.IgnoreCertificate
		defaultOptions.UpdateAccessTokenCallback = options.UpdateAccessTokenCallback
	}

	if logger == nil {
		logger = createPassThroughLogger()
	}

	tr := &http.Transport{
		TLSClientConfig: &tls.Config{
			InsecureSkipVerify: defaultOptions.IgnoreCertificate,
			RootCAs:            defaultOptions.RootCAs},
	}

	endpoint = strings.TrimRight(endpoint, "/")

	tokenCallback := func(newToken string) {
		c.options.TokenOptions.AccessToken = newToken
		if c.options.UpdateAccessTokenCallback != nil {
			c.options.UpdateAccessTokenCallback(newToken)
		}
	}

	restClient := &restClient{
		httpClient: &http.Client{Transport: tr},
		logger:     logger,
		UpdateAccessTokenCallback: tokenCallback,
	}

	c = &Client{Endpoint: endpoint, restClient: restClient, logger: logger}

	// Ensure a copy of options is made, rather than using a pointer
	// which may change out from underneath if misused by the caller.
	c.options = *defaultOptions
	c.Status = &StatusAPI{c}
	c.Tenants = &TenantsAPI{c}
	c.Tasks = &TasksAPI{c}
	c.Projects = &ProjectsAPI{c}
	c.Flavors = &FlavorsAPI{c}
	c.Images = &ImagesAPI{c}
	c.Disks = &DisksAPI{c}
	c.VMs = &VmAPI{c}
	c.Hosts = &HostsAPI{c}
	c.Deployments = &DeploymentsAPI{c}
	c.ResourceTickets = &ResourceTicketsAPI{c}
	c.Networks = &NetworksAPI{c}
	c.Services = &ServicesAPI{c}
	c.Auth = &AuthAPI{c}
	c.AvailabilityZones = &AvailabilityZonesAPI{c}
	c.Info = &InfoAPI{c}
	c.Routers = &RoutersAPI{c}
	c.Subnets = &SubnetsAPI{c}
	c.System = &SystemAPI{c}
	c.Zones = &ZonesAPI{c}
	c.Infra = &InfraAPI{c}
	c.InfraHosts = &InfraHostsAPI{c}

	// Tell the restClient about the Auth API so it can request new
	// acces tokens when they expire
	restClient.Auth = c.Auth
	return
}

// Creates a new photon client with specified options and http.Client.
// Useful for functional testing where http calls must be mocked out.
// If options is nil, default options will be used.
func NewTestClient(endpoint string, options *ClientOptions, httpClient *http.Client) (c *Client) {
	c = NewClient(endpoint, options, nil)
	c.restClient.httpClient = httpClient
	return
}

func createPassThroughLogger() (l *log.Logger) {
	// ioutil.Discard makes all logging operation be a no-op.
	return log.New(ioutil.Discard, "", log.LstdFlags)
}
