from parallels.core import messages
import logging
import posixpath

from parallels.core.utils.common import obj
from parallels.core.utils import unix_utils

logger = logging.getLogger(__name__)

PERMISSION_CHANGE_MODE = obj(
	# change permissions on specified file only
	SELF='self', 
	# recursively change permissions on all files inside a directory
	# (but do not touch the directory itself, and do not touch directories)
	SUBFILES_AND_SUBDIRS='sub',
)


class PermissionRule(object):
	"""Entity that represents a rule to change file permissions"""
	def __init__(self, mode, path, user=None, group=None, permissions=None):
		"""Create object
		Arguments:
		mode - one of PERMISSION_CHANGE_MODE
		path - (string) relative path to file/directory to change permissions
		user - (string) system user name, for chown input
		group - (string) system group name, for chgrp input
		permissions - (string) permissions, for chmod input
		"""
		self.mode = mode
		self.path = path
		self.user = user
		self.group = group
		self.permissions = permissions

	def __repr__(self):
		return \
			'PermissionRule(mode=%r, path=%r, user=%r, group=%r, permissions=%r)' % (
				self.mode, self.path, self.user, self.group, self.permissions
			)


def bulk_change_permissions(runner, root_path, permissions_list):
	"""Change permissions for files according to permissions list
	
	permissions_list is a list of PermissionRule objects
	root_path - is prepended to path attribute of each permission rule
	
	Function iterates by the list one-by-one and changes permissions,
	so consider to put them in correct order
	"""
	logger.debug(
		messages.CHANGE_PERMISSIONS_ACCORDING_FOLLOWING_RULES_S,
		permissions_list
	)
		
	for permission in permissions_list:
		full_path = posixpath.join(
			root_path, permission.path
		)

		if not unix_utils.file_exists(runner, full_path):
			continue # simply ignore if file/dir does not exist

		if permission.mode == PERMISSION_CHANGE_MODE.SELF:
			if permission.user is not None:
				runner.sh('chown {user} {path}', dict(
					user=permission.user, path=full_path
				))
			if permission.group is not None:
				runner.sh('chgrp {group} {path}', dict(
					group=permission.group, path=full_path
				))
			if permission.permissions is not None:
				runner.sh('chmod {perm} {path}', dict(
					perm=permission.permissions, path=full_path
				))
		elif permission.mode == PERMISSION_CHANGE_MODE.SUBFILES_AND_SUBDIRS:
			runner.sh(
				'find {path} -mindepth 1 -exec chown {user}:{group} {{}} \\;',
				dict(
					path=full_path, 
					user=permission.user,
					group=permission.group
				)
			)
		else:
			assert(False)

