func (c *CommuteCmd) String() string {
	return fmt.Sprintf("From '%v' to '%v'", c.From, c.To)
}
String returns a string representation of the CommuteCmd.
package cmd
import (
	"errors"
	"fmt"
	"strings"
	"time"
	"github.com/KyleBanks/commuter/pkg/geo"
)
const (
	DefaultLocationAlias = "default"
)
var (
	ErrDefaultFromMissing = errors.New("missing -from or -from-current parameter")
	ErrDefaultToMissing = errors.New("missing -to or -to-current parameter")
	ErrNoCommuteMethod = errors.New("at least one commute method must be specified")
	ErrFromAndFromCurrentProvided = errors.New("cannot use -from and -from-current arguments")
	ErrToAndToCurrentProvided = errors.New("cannot use -to and -to-current arguments")
)
type CommuteCmd struct {
	From        string
	FromCurrent bool
	To        string
	ToCurrent bool
	Drive   bool
	Walk    bool
	Bike    bool
	Transit bool
	Durationer Durationer
	Locator    Locator
}
func (c *CommuteCmd) Run(conf *Configuration, i Indicator) error {
	modes := c.modes()
	multiMode := len(modes) > 1
	for _, m := range modes {
		d, err := c.Durationer.Duration(c.From, c.To, m)
		if err != nil {
			return err
		}
		var method string
		if multiMode {
			method = fmt.Sprintf("%v: ", m)
		}
		i.Indicate("%v%v", method, c.format(*d))
	}
	return nil
}
func (c *CommuteCmd) format(d time.Duration) string {
	pluralize := func(s string, i int) string {
		if i != 1 {
			s += "s"
		}
		return s
	}
	var out []string
	hours := int(d.Hours())
	minutes := int(d.Minutes())
	if hours > 0 {
		minutes -= (hours * 60)
		out = append(out, fmt.Sprintf("%v %v", hours, pluralize("Hour", hours)))
	}
	out = append(out, fmt.Sprintf("%v %v", minutes, pluralize("Minute", minutes)))
	return strings.Join(out, " ")
}
func (c *CommuteCmd) modes() []geo.TravelMode {
	var modes []geo.TravelMode
	if c.Drive {
		modes = append(modes, geo.Drive)
	}
	if c.Walk {
		modes = append(modes, geo.Walk)
	}
	if c.Bike {
		modes = append(modes, geo.Bike)
	}
	if c.Transit {
		modes = append(modes, geo.Transit)
	}
	return modes
}
func (c *CommuteCmd) Validate(conf *Configuration) (err error) {
	if !c.Drive && !c.Walk && !c.Bike && !c.Transit {
		return ErrNoCommuteMethod
	}
	c.From, err = c.setLocation(conf, c.From, c.FromCurrent, ErrFromAndFromCurrentProvided, ErrDefaultFromMissing)
	if err != nil {
		return
	}
	c.To, err = c.setLocation(conf, c.To, c.ToCurrent, ErrToAndToCurrentProvided, ErrDefaultToMissing)
	if err != nil {
		return
	}
	return
}
func (c *CommuteCmd) setLocation(conf *Configuration, value string, useCurrent bool, bothProvided error, missing error) (string, error) {
	if useCurrent && len(value) > 0 && value != DefaultLocationAlias {
		return "", bothProvided
	}
	var err error
	if useCurrent {
		value, err = c.locate(conf)
	} else {
		value = c.alias(conf, value)
	}
	if err != nil {
		return "", err
	}
	if len(value) == 0 {
		return "", missing
	}
	return value, nil
}
func (c *CommuteCmd) alias(conf *Configuration, value string) string {
	val, ok := conf.Locations[value]
	if !ok {
		return value
	}
	return val
}
func (c *CommuteCmd) locate(conf *Configuration) (string, error) {
	lat, long, err := c.Locator.CurrentLocation()
	if err != nil {
		return "", err
	}
	return fmt.Sprintf("%v,%v", lat, long), nil
}