func (c *Client) PlaceDetails(ctx context.Context, r *PlaceDetailsRequest) (PlaceDetailsResult, error) {
	if r.PlaceID == "" {
		return PlaceDetailsResult{}, errors.New("maps: PlaceID missing")
	}
	var response struct {
		Result           PlaceDetailsResult `json:"result"`
		HTMLAttributions []string           `json:"html_attributions"`
		commonResponse
	}
	if err := c.getJSON(ctx, placeDetailsAPI, r, &response); err != nil {
		return PlaceDetailsResult{}, err
	}
	if err := response.StatusError(); err != nil {
		return PlaceDetailsResult{}, err
	}
	response.Result.HTMLAttributions = response.HTMLAttributions
	return response.Result, nil
}
PlaceDetails issues the Places API Place Details request and retrieves the response
package maps
import (
	"errors"
	"fmt"
	"image"
	"io"
	"net/url"
	"strconv"
	"strings"
	"golang.org/x/net/context"
	_ "image/jpeg"
)
var placesNearbySearchAPI = &apiConfig{
	host:            "https://maps.googleapis.com",
	path:            "/maps/api/place/nearbysearch/json",
	acceptsClientID: true,
}
func (c *Client) NearbySearch(ctx context.Context, r *NearbySearchRequest) (PlacesSearchResponse, error) {
	if r.PageToken == "" {
		if r.Location == nil {
			return PlacesSearchResponse{}, errors.New("maps: Location and PageToken both missing")
		}
		if r.Radius == 0 && r.RankBy != RankByDistance {
			return PlacesSearchResponse{}, errors.New("maps: Radius and PageToken both missing")
		}
		if r.Radius > 0 && r.RankBy == RankByDistance {
			return PlacesSearchResponse{}, errors.New("maps: Radius specified with RankByDistance")
		}
		if r.RankBy == RankByDistance && r.Keyword == "" && r.Name == "" && r.Type == "" {
			return PlacesSearchResponse{}, errors.New("maps: RankBy=distance and Keyword, Name and Type are missing")
		}
	}
	var response struct {
		Results          []PlacesSearchResult `json:"results"`
		HTMLAttributions []string             `json:"html_attributions"`
		NextPageToken    string               `json:"next_page_token"`
		commonResponse
	}
	if err := c.getJSON(ctx, placesNearbySearchAPI, r, &response); err != nil {
		return PlacesSearchResponse{}, err
	}
	if err := response.StatusError(); err != nil {
		return PlacesSearchResponse{}, err
	}
	return PlacesSearchResponse{response.Results, response.HTMLAttributions, response.NextPageToken}, nil
}
func (r *NearbySearchRequest) params() url.Values {
	q := make(url.Values)
	if r.Location != nil {
		q.Set("location", r.Location.String())
	}
	if r.Radius != 0 {
		q.Set("radius", fmt.Sprint(r.Radius))
	}
	if r.Keyword != "" {
		q.Set("keyword", r.Keyword)
	}
	if r.Language != "" {
		q.Set("language", r.Language)
	}
	if r.MinPrice != "" {
		q.Set("minprice", string(r.MinPrice))
	}
	if r.MaxPrice != "" {
		q.Set("maxprice", string(r.MaxPrice))
	}
	if r.Name != "" {
		q.Set("name", r.Name)
	}
	if r.OpenNow {
		q.Set("opennow", "true")
	}
	if r.RankBy != "" {
		q.Set("rankby", string(r.RankBy))
	}
	if r.Type != "" {
		q.Set("type", string(r.Type))
	}
	if r.PageToken != "" {
		q.Set("pagetoken", r.PageToken)
	}
	return q
}
type NearbySearchRequest struct {
	Location *LatLng
	Radius uint
	Keyword string
	Language string
	MinPrice PriceLevel
	MaxPrice PriceLevel
	Name string
	OpenNow bool
	RankBy
	Type PlaceType
	PageToken string
}
var placesTextSearchAPI = &apiConfig{
	host:            "https://maps.googleapis.com",
	path:            "/maps/api/place/textsearch/json",
	acceptsClientID: true,
}
func (c *Client) TextSearch(ctx context.Context, r *TextSearchRequest) (PlacesSearchResponse, error) {
	if r.Query == "" && r.PageToken == "" {
		return PlacesSearchResponse{}, errors.New("maps: Query and PageToken both missing")
	}
	if r.Location != nil && r.Radius == 0 {
		return PlacesSearchResponse{}, errors.New("maps: Radius missing, required with Location")
	}
	var response struct {
		Results          []PlacesSearchResult `json:"results"`
		HTMLAttributions []string             `json:"html_attributions"`
		NextPageToken    string               `json:"next_page_token"`
		commonResponse
	}
	if err := c.getJSON(ctx, placesTextSearchAPI, r, &response); err != nil {
		return PlacesSearchResponse{}, err
	}
	if err := response.StatusError(); err != nil {
		return PlacesSearchResponse{}, err
	}
	return PlacesSearchResponse{response.Results, response.HTMLAttributions, response.NextPageToken}, nil
}
func (r *TextSearchRequest) params() url.Values {
	q := make(url.Values)
	q.Set("query", r.Query)
	if r.Location != nil {
		q.Set("location", r.Location.String())
	}
	if r.Radius != 0 {
		q.Set("radius", fmt.Sprint(r.Radius))
	}
	if r.Language != "" {
		q.Set("language", r.Language)
	}
	if r.MinPrice != "" {
		q.Set("minprice", string(r.MinPrice))
	}
	if r.MaxPrice != "" {
		q.Set("maxprice", string(r.MaxPrice))
	}
	if r.OpenNow {
		q.Set("opennow", "true")
	}
	if r.Type != "" {
		q.Set("type", string(r.Type))
	}
	if r.PageToken != "" {
		q.Set("pagetoken", r.PageToken)
	}
	return q
}
type TextSearchRequest struct {
	Query string
	Location *LatLng
	Radius uint
	Language string
	MinPrice PriceLevel
	MaxPrice PriceLevel
	OpenNow bool
	Type PlaceType
	PageToken string
}
var placesRadarSearchAPI = &apiConfig{
	host:            "https://maps.googleapis.com",
	path:            "/maps/api/place/radarsearch/json",
	acceptsClientID: true,
}
func (c *Client) RadarSearch(ctx context.Context, r *RadarSearchRequest) (PlacesSearchResponse, error) {
	if r.Location == nil {
		return PlacesSearchResponse{}, errors.New("maps: Location is missing")
	}
	if r.Radius == 0 {
		return PlacesSearchResponse{}, errors.New("maps: Radius is missing")
	}
	if r.Keyword == "" && r.Name == "" && r.Type == "" {
		return PlacesSearchResponse{}, errors.New("maps: Keyword, Name and Type are missing")
	}
	var response struct {
		Results          []PlacesSearchResult `json:"results"`
		HTMLAttributions []string             `json:"html_attributions"`
		NextPageToken    string               `json:"next_page_token"`
		commonResponse
	}
	if err := c.getJSON(ctx, placesRadarSearchAPI, r, &response); err != nil {
		return PlacesSearchResponse{}, err
	}
	if err := response.StatusError(); err != nil {
		return PlacesSearchResponse{}, err
	}
	return PlacesSearchResponse{response.Results, response.HTMLAttributions, response.NextPageToken}, nil
}
func (r *RadarSearchRequest) params() url.Values {
	q := make(url.Values)
	if r.Location != nil {
		q.Set("location", r.Location.String())
	}
	if r.Radius != 0 {
		q.Set("radius", fmt.Sprint(r.Radius))
	}
	if r.Keyword != "" {
		q.Set("keyword", r.Keyword)
	}
	if r.MinPrice != "" {
		q.Set("minprice", string(r.MinPrice))
	}
	if r.MaxPrice != "" {
		q.Set("maxprice", string(r.MaxPrice))
	}
	if r.Name != "" {
		q.Set("name", r.Name)
	}
	if r.OpenNow {
		q.Set("opennow", "true")
	}
	if r.Type != "" {
		q.Set("type", string(r.Type))
	}
	return q
}
type RadarSearchRequest struct {
	Location *LatLng
	Radius uint
	Keyword string
	MinPrice PriceLevel
	MaxPrice PriceLevel
	Name string
	OpenNow bool
	Type PlaceType
}
type PlacesSearchResponse struct {
	Results []PlacesSearchResult
	HTMLAttributions []string
	NextPageToken string
}
type PlacesSearchResult struct {
	FormattedAddress string `json:"formatted_address"`
	Geometry AddressGeometry `json:"geometry"`
	Name string `json:"name"`
	Icon string `json:"icon"`
	PlaceID string `json:"place_id"`
	Scope string `json:"scope"`
	Rating float32 `json:"rating"`
	Types []string `json:"types"`
	OpeningHours *OpeningHours `json:"opening_hours"`
	Photos []Photo `json:"photos"`
	AltIDs []AltID `json:"alt_ids"`
	PriceLevel int `json:"price_level"`
	Vicinity string `json:"vicinity"`
	PermanentlyClosed bool `json:"permanently_closed"`
}
type AltID struct {
	PlaceID string `json:"place_id"`
	Scope string `json:"scope"`
}
var placeDetailsAPI = &apiConfig{
	host:            "https://maps.googleapis.com",
	path:            "/maps/api/place/details/json",
	acceptsClientID: true,
}