'''
Full body sensual massage
or finite state machine
'''

import copy,json


def validate(machine):
	stateLst = [	state
			for name,state in machine.items()
			if name != 'begin'	]
	missing = [	next
			for next in state['next'].values()
			if next not in machine	]
	if missing:
		raise Exception('state %s is missing from %s' %
				(next,machine))
	if 'begin' not in machine:
		raise Exception('begin is missing from %s' %
				machine)
	if machine['begin'] not in machine:
		raise Exception('begin state %s is missing from %s' %
				(machine['begin'],machine))
	return machine

def next(signal,machine):
	name = machine['begin']
	state = machine[name]
	next = state['next']
	if signal in next:
		newmachine = copy.copy(machine)
		newmachine['begin'] = next[signal]
		return newmachine
	return machine

def state(machine):
	return machine['begin']

if __name__ == '__main__':
	pulse = {
		'begin' : 'off',
		'on' : {
			'next' : {},
			'default' : 'off'
		},
		'off' : {
			'next' : {
				'trigger' : 'on'
				},
			'default' : 'off'
		}
	}

	print('pusle validation %s' % validate(pulse))
	print('pulse machine first step [%s]' % state(pulse))
        print('pusle machine after trigger [%s]' % 
		state(next('trigger',pulse)))
	print('pulse machine after two trigger [%s]' % 
		state(next('trigger',next('trigger',pulse))))
	print('pulse machine after another trigger [%s]' % 
		state(next('trigger',next('trigger',next('trigger',pulse)))))

	switch = {
		'begin' : 'off',
		'on' : {
			'next' : {
				'trigger' : 'off'
			},
			'default' : 'on'
		},
		'off' : {
			'next' : {
				'trigger' : 'on'
			},
			'default' : 'off'
		}
	}

        print('switch validation %s' % validate(switch))
        print('switch machine first step [%s]' % state(switch))        
        print('switch machine after trigger [%s]' % 
		state(next('trigger',switch)))
        print('switch machine two trigger [%s]' % 
		state(next('trigger',next('trigger',switch))))
        print('switch machine after another trigger [%s]' % 
		state(next('trigger',next('trigger',next('trigger',switch)))))
        print('switch machine after again another trigger [%s]' % 
		state(next('trigger',next('trigger',next('trigger',next('trigger',switch))))))


