<?php
/*
Plugin Name: BuddyPress group maps
Description: Allows your BuddyPress groups to add location maps.
Plugin URI: http://premium.wpmudev.org/project/wordpress-google-maps-plugin
Version: 1.0
Author: Ve Bailovity (Incsub)
*/

class Agm_Bp_GroupMaps {

	const SLUG = 'map';

	private function __construct () {}

	public static function serve () {
		$me = new Agm_Bp_GroupMaps;
		$me->_add_hooks();
	}

	private function _add_hooks () {
		// Group creation
		add_action('bp_after_group_details_creation_step', array($this, 'bp_group_create_get_output'));
		add_action('groups_create_group_step_save_group-details', array($this, 'bp_group_create_save_data'));

		// Map settings for admins
		add_action('bp_after_group_details_admin', array($this, 'bp_group_edit_get_output'));
		add_action('groups_details_updated', array($this, 'bp_group_edit_save_data'));

		// Output
		add_action('bp_init', array($this, 'add_maps_tab'));
		add_action('bp_before_group_members_content', array($this, 'bp_group_members_get_output'));

		// Shortcode
		add_shortcode('agm_group_map', array($this, 'process_group_shortcode'));
		add_shortcode('agm_groups_map', array($this, 'process_groups_shortcode'));
	}

	private function _get_current_group () {
		global $bp;
		if (!$bp->is_single_item) return false;

		$group = $bp->groups->current_group;
		if (!$group) return false;

		return $group;
	}

	// Singular form
	function process_group_shortcode ($args=array(), $content=false) {
		$group_args = wp_parse_args($args, array(
			'group_id' => false,
		));
		if (empty($group_args['group_id'])) return $content;
		$rpl = new AgmMarkerReplacer;
		$overrides = $rpl->arguments_to_overrides($args);
		$tag = $this->create_group_maps_user_body($group_args['group_id'], $overrides);
		return !empty($tag)
			? $tag
			: $content
		;
	}

	// Plural form
	function process_groups_shortcode ($args=array(), $content=false) {
		$groups_args = wp_parse_args($args, array(
			'exclude' => false,
			'show_members' => false,
			'group_marker' => 'icon',
		));

		$exclude = !empty($groups_args['exclude'])
			? array_filter(array_map('intval', array_map('trim', explode(',', $groups_args['exclude']))))
			: array()
		;

		$rpl = new AgmMarkerReplacer;
		$overrides = $rpl->arguments_to_overrides($args);
		$raw = groups_get_groups(array(
			'user_id' => false,
			'exclude' => $exclude,
		));
		if (empty($raw['groups'])) return $content;
		$maps = array();
		foreach ($raw['groups'] as $group) {
			if (empty($group->id)) continue;
			$map = $this->_get_group_map($group->id, array(
				'show_members' => $groups_args['show_members'], // show if set
				'group_marker' => $groups_args['group_marker'], // icon|avatar
			));
			if (!$map) continue;
			$maps[] = $map;
		}
		if (empty($maps)) return $content;

		return $rpl->create_overlay_tag($maps, $overrides);
	}

	function add_maps_tab () {
		$group = $this->_get_current_group();
		if (!$group) return false;

		$groups_link = bp_get_group_permalink($group);

		// Show separate map page if set so in settings
		$data = groups_get_groupmeta($group->id, "agm-group_map");
		if (empty($data["map_tab"])) return false;

		if ($this->_check_user_map_show_privileges(get_current_user_id(), $group->id)) {
			bp_core_new_subnav_item(array(
				'name' => __('Group Map', 'agm_google_maps'),
				'slug' => self::SLUG . '-show',
				'parent_url' => $groups_link,
				'parent_slug' => $group->slug,
				'screen_function' => array($this, 'bind_bp_groups_user_page'),
			));
		}
	}
	function bp_group_members_get_output () {
		$group = $this->_get_current_group();
		if (!$group) return false;

		// Show separate map page if set so in settings
		$data = groups_get_groupmeta($group->id, "agm-group_map");
		if (empty($data["map_tab"])) return false;

		// Show group map on members list page if set so in settings
		$data = groups_get_groupmeta($group->id, "agm-group_map");
		if (empty($data["map_list"])) return false;
		$this->show_group_maps_user_body();
	}


	function bp_group_create_save_data () {
		global $bp;
		$this->_save_data($bp->groups->new_group_id);
	}
	function bp_group_edit_save_data ($group_id) {
		$this->_save_data($group_id);
	}
	function _save_data ($group_id) {
		global $current_user;
		if (!$group_id || !groups_is_user_admin($current_user->id, $group_id)) return false;
		if (empty($_POST["agm-group_map"])) return false;
		groups_update_groupmeta($group_id, "agm-group_map", stripslashes_deep($_POST["agm-group_map"]));
		update_option("_agm-group_map-for-{$group_id}", false);
	}


	function bp_group_create_get_output () {
		if (!bp_user_can_create_groups()) return false;
		$this->_show_group_maps_admin_body();
	}
	function bp_group_edit_get_output () {
		global $bp, $current_user;
		// Only Group Admins see the settings area
		if (!groups_is_user_admin($current_user->id, $bp->groups->current_group->id)) return false;
		$this->_show_group_maps_admin_body($bp->groups->current_group->id);
	}
	private function _show_group_maps_admin_body ($group_id=false) {
		$data = groups_get_groupmeta($group_id, "agm-group_map");
		$data = wp_parse_args(
			(is_array($data) ? $data : array()),
			array(
				"address" => "",
				"show_map" => "all",
				"map_tab" => 1,
				"map_list" => 1,
				"member_locations" => 1,
			)
		);
		?>
	<fieldset id="agm-group_map">
		<legend style="display:none"><?php _e('Group map', 'agm_google_maps'); ?></legend>
		<?php
		// - This group has location: address (please use full address)
		?>
		<label for="agm-group_map-address"><?php _e('This group has address:', 'agm_google_maps'); ?></label>
		<input type="text" name="agm-group_map[address]" id="agm-group_map-address" value="<?php esc_attr_e($data["address"]); ?>" />
		<?php
		// - Show group map to: a) all, b) members, c) moderators
		?>
		<label><?php _e('Show group map to:', 'agm_google_maps'); ?></label>
		<label for="agm-group_map-show_map-all">
			<input type="radio" id="agm-group_map-show_map-all" name="agm-group_map[show_map]" value="all" <?php checked("all", $data["show_map"]); ?> />
			<?php _e('All', 'agm_google_maps'); ?>
		</label>
		<label for="agm-group_map-show_map-members">
			<input type="radio" id="agm-group_map-show_map-members" name="agm-group_map[show_map]" value="members" <?php checked("members", $data["show_map"]); ?> />
			<?php _e('Members', 'agm_google_maps'); ?>
		</label>
		<label for="agm-group_map-show_map-moderators">
			<input type="radio" id="agm-group_map-show_map-moderators" name="agm-group_map[show_map]" value="moderators" <?php checked("moderators", $data["show_map"]); ?> />
			<?php _e('Moderators', 'agm_google_maps'); ?>
		</label>
		<?php
		// - Show separate Group Map tab
		?>
		<label for="agm-group_map-map_tab">
			<input type="hidden" name="agm-group_map[map_tab]" value="" />
			<input type="checkbox" id="agm-group_map-map_tab" name="agm-group_map[map_tab]" value="1" <?php checked(1, $data["map_tab"]); ?> />
			<?php _e('Show separate Group Map tab', 'agm_google_maps'); ?>
		</label>
		<?php
		// - Show map on members list page
		?>
		<label for="agm-group_map-map_list">
			<input type="hidden" name="agm-group_map[map_list]" value="" />
			<input type="checkbox" id="agm-group_map-map_list" name="agm-group_map[map_list]" value="1" <?php checked(1, $data["map_list"]); ?> />
			<?php _e('Show map on members list page', 'agm_google_maps'); ?>
		</label>
		<?php
		// - Also show members locations (requires BuddyPress Profile maps add-on)
		if (class_exists('Agm_Bp_Pm_UserPages')) {
		?>
		<label for="agm-group_map-member_locations">
			<input type="hidden" name="agm-group_map[member_locations]" value="" />
			<input type="checkbox" id="agm-group_map-member_locations" name="agm-group_map[member_locations]" value="1" <?php checked(1, $data["member_locations"]); ?> />
			<?php _e('Also show members locations', 'agm_google_maps'); ?>
			<em><?php _e('(requires BuddyPress Profile maps add-on)', 'agm_google_maps'); ?></em>
		</label>
		<?php
		}
		// end form
		?>
	</fieldset>
		<?php
	}

	function bind_bp_groups_user_page () {
		add_action('bp_template_content', array($this, 'show_group_maps_user_body'));
		bp_core_load_template(apply_filters('bp_core_template_plugin', 'groups/single/plugins'));
	}
	function show_group_maps_user_body ($group_id=false, $overrides=array()) {
		echo $this->create_group_maps_user_body($group_id, $overrides);
	}
	function create_group_maps_user_body ($group_id=false, $overrides=array()) {
		if (!$group_id) {
			global $bp;
			$group_id = $bp->groups->current_group->id;
		}
		if (!$group_id) return false;
		$user_id = get_current_user_id();
		$allow = $this->_check_user_map_show_privileges($user_id, $group_id);

		return $allow
			? $this->_get_group_map_tag($group_id, $overrides)
			: false
		;
	}

	private function _check_user_map_show_privileges ($user_id, $group_id) {
		$allow = false;
		$data = groups_get_groupmeta($group_id, "agm-group_map");
		$show = !empty($data["show_map"]) ? $data["show_map"] : "all";
		if ("all" == $show || is_super_admin()) {
			$allow = true;
		} else {
			if ("members" == $show) {
				$allow = groups_is_user_member($user_id, $group_id);
			} else if ("moderators" == $show) {
				$allow = groups_is_user_mod($user_id, $group_id) || groups_is_user_admin($user_id, $group_id);
			}
		}
		return $allow;
	}

	private function _get_group_map ($group_id, $data_overrides=array()) {
		$data_overrides = wp_parse_args($data_overrides, array(
			'show_members' => true,
		));
		$data = groups_get_groupmeta($group_id, "agm-group_map");
		$model = new AgmMapModel;
		$map_id = get_option("_agm-group_map-for-{$group_id}", false);
		$address = !empty($data["address"]) ? $data["address"] : apply_filters('agm-group_map-default_group_address', false, $group_id, $data);
		$map = false;

		if ($map_id) {
			$map = $model->get_map($map_id);
		} else if (!$map_id && $address) {
			$map_id = $model->autocreate_map(false, false, false, $address);
			if (!$map_id) return false;
			update_option("_agm-group_map-for-{$group_id}", $map_id);
			$map = $model->get_map($map_id);
		} else {
			$map = $model->get_map_defaults();
			$map['defaults'] = $model->get_map_defaults();
			$map['id'] = $group_id . md5(time() . rand());
			$map['show_map'] = 1;
			$map['show_markers'] = 0;
			$map['markers'] = array();
		}

		if (!empty($data_overrides['group_marker']) && 'avatar' == $data_overrides['group_marker'] && function_exists('bp_core_fetch_avatar')) {
			if (1 != count($map['markers'])) continue;
			if (empty($map['markers'][0])) continue;
			$avatar = bp_core_fetch_avatar(array(
				'object' => 'group',
				'item_id' => $group_id,
				'width' => 32, // Hardcoding sizes, change this
				'height' => 32,
				'html' => false,
			));
			if (!empty($avatar)) $map['markers'][0]['icon'] = $avatar;
		}

		if (!empty($data['member_locations']) && !empty($data_overrides['show_members']) && class_exists('Agm_Bp_Pm_UserPages')) {
			$profile = new Agm_Bp_Pm_UserPages;
			$markers = $map['markers'];
			$members = groups_get_group_members($group_id);
			if ($members && !empty($members['members'])) foreach ($members['members'] as $member) {
				$marker = $profile->member_to_marker($member->ID);
				if ($marker) $markers[] = $marker;
			}
			$map['markers'] = $markers;
		}

		if (empty($map['markers'])) return false;
		return $map;
	}

	private function _get_group_map_tag ($group_id, $overrides=array()) {
		$map = $this->_get_group_map($group_id);
		if (!$map) return false;

		$codec = new AgmMarkerReplacer;
		return $codec->create_tag($map, $overrides);
	}
}

Agm_Bp_GroupMaps::serve();