"""
This program shows how to declare and use properties.
Property declarations always start with one of three keywords:
	* pro
	* get
	* set
"""


class Person

	var _name as String

	cue init(name as String)
		base.init
		_name = name

	pro name as String
		"""
		The name of the person. Setting the name trims preceding and
		trailing whitespace from the value.
		"""
		get
			return _name
		set
			# `value` is an implicit argument in all property setters:
			_name = value.trim

	def printName
		print .name

	def sayHello
		print 'Hi, my name is [.name]'


class Program

	def main is shared
		p = Person('chuck')
		print p.name
		assert p.name == 'chuck'
		p.name = 'Chuck'


# Many properties just cover for an underlying variable. When that
# is the case, you can use a shortcut syntaxes. Later, you can
# change the property to the full form in order to add logic.

# In this shortcut syntax, properties and their backing vars are
# declared in one line:

class Person2

	cue init(name as String)
		base.init
		_name = name

	pro name from var as String
	
	pro age from var as int


# In this shortcut syntax, the vars were already declared so
# the property simply "... from var":

class Person3

	var _name as String
	var _age as int

	cue init(name as String)
		base.init
		_name = name

	pro name from var
		"""
		The "from var" indicates that the type of the property, as well
		as its value, is taken from the class variable with the matching
		name (underscore + property name). When you later want to add
		code for this property, just chop off the "from var" and write
		the full property (pro foo as Type; get ...; set ...)
		"""

	pro age from var


# If the underlying variable name is different than the property name,
# you can specify that name instead of "var":

class Person4

	var _name as String

	cue init(name as String)
		base.init
		_name = name

	pro nombre from _name


# Properties can be read-only:

class Person5

	cue init(name as String)
		base.init
		_name = name

	get name from var as String

	get lowerName as String
		return _name.toLower


# Properties can be write-only:

class Parts

	var _stuff = List<of Object>()

	set contents as List<of Object>
		_stuff.clear
		for item in value
			_stuff.add(item)


# Properties can be protected, typically with an underscore, although
# it's not very common. Then only this class and subclasses can invoke
# them:

class Foo

	get _mol as int  # underscore implies `protected`
		return 42

	get goldenRatio as number is protected   # `protected` can be explicit
		return 1.618033989

	def doSomething
		# Note that when accessing underscored members, you no longer
		# use the preceding ".":
		assert _mol == 42

		# Without an underscore, the "." is required:
		assert .goldenRatio > 1.6
