<?php

/**
 * Implements hook_permission()
 */
function profile_sync_email_permission() {
  return array(
    'administer profile sync email' => array(
      'title' => t('Administer Profile2 sync email'),
      'description' => t('Select profile email field to sync to user account email.'),
    ),
  );
} // profile_sync_email_permission()

/**
 * Implements hook_form_FORM_ID_alter()
 */
function profile_sync_email_form_field_ui_field_edit_form_alter(&$form, &$form_state, $form_id) {
  // if this is an email field on a profile
  if ($form['#field']['type'] == 'email' && $form['instance']['entity_type']['#value'] == 'profile2') {
    $sync_field = variable_get('profile_sync_email_instance', -1);
    $form['profile_sync_email'] = array(
      '#type' => 'checkbox',
      '#title' => t('Sync this email field to the user account'),
      '#description' => t('When checked, this field will update the user account email and vice versa.'),
      '#default_value' => ($sync_field == $form['#instance']['id'])? 1 : 0,
    );
    $form['#submit'][] = 'profile_sync_email_submit';
  } // if email on a profile
} // profile_sync_email_form_alter()

/**
 * form submit
 */
function profile_sync_email_submit($form, &$form_state) {
  if (isset($form_state['values']['profile_sync_email']) && $form_state['values']['profile_sync_email'] == 1) {
    variable_set('profile_sync_email_instance', $form['#instance']['id']);
  } // if
} // profile_sync_email_submit()

/**
 * hook_form_alter()
 */
function profile_sync_email_form_alter(&$form, &$form_state, $form_id) {
  // get the sync field info
  $instance_info = profile_sync_email_instance_info();

   // if this form is for the profile
  if (isset($instance_info->bundle) && isset($instance_info->field_name) && isset($form['profile_' . $instance_info->bundle][$instance_info->field_name])) {

    if (!isset($form_state['build_info']['args'][0]->uid) || !is_numeric($form_state['build_info']['args'][0]->uid)) return; // no user, end here

    // load the user and set the email field
    $user = user_load($form_state['build_info']['args'][0]->uid);
    $field = &$form['profile_' . $instance_info->bundle][$instance_info->field_name];
    $field[$field['#language']][0]['email']['#default_value'] = $user->mail;

    // add validation on the email field
    $field[$field['#language']][0]['email']['#element_validate'][] = 'profile_sync_email_validate_email';

  } // if field exists
} // profile_sync_email_form_alter()

/**
 * validation callback
 */
function profile_sync_email_validate_email($element, &$form_state, $form) {
  if (!empty($element['#value'])) {
    $email_user = user_load_by_mail($element['#value']);
    if (isset($email_user->uid) && $email_user->uid != $form_state['build_info']['args'][0]->uid) {
      form_error($element, t('The email address %email is being used by another user', array('%email' => $element['#value'])));
    }
  }
} // profile_sync_email_validate_email()


/**
 * hook_profile2_insert(), hook_profile2_update()
 */
function profile_sync_email_profile2_insert($profile) {
  profile_sync_email_profile2($profile);
} // profile_sync_email_profile2_insert()
function profile_sync_email_profile2_update($profile) {
  profile_sync_email_profile2($profile);
} // profile_sync_email_profile2_update()

function profile_sync_email_profile2($profile) {
  $sync_field = profile_sync_email_instance_info();
  $user = user_load($profile->uid);
  if (isset($profile->{$sync_field->field_name}[LANGUAGE_NONE][0]['email'])) {
    $email = $profile->{$sync_field->field_name}[LANGUAGE_NONE][0]['email'];
  } else {
    $email = '';
  }
  if ($user->mail != $email && !empty($email) && (!isset($_SESSION['profile_sync_email_profile']) || !$_SESSION['profile_sync_email_profile'])) {
    $user->mail = $email;
  
    $_SESSION['profile_sync_email_profile'] = TRUE;
    user_save($user);
    $_SESSION['profile_sync_email_profile'] = FALSE;
  }
} // profile_sync_email_profile2()

/**
 * Update the profile whenever the user is updated
 * hook_user_insert(), hook_user_update()
 */
function profile_sync_email_user_insert(&$edit, $account, $category) {
  // test for a profile
  $sync_field = profile_sync_email_instance_info();
  profile_sync_email_create_profile($account, $sync_field->bundle);
  // sync the profile
  profile_sync_email_user($edit, $account, $category);
} // profile_sync_email_user_insert()
function profile_sync_email_user_update(&$edit, $account, $category) {
  // test for a profile
  $sync_field = profile_sync_email_instance_info();
  profile_sync_email_create_profile($account, $sync_field->bundle);
  // sync the profile
  profile_sync_email_user($edit, $account, $category);
} // profile_sync_email_user_update()

function profile_sync_email_user(&$edit, $account, $category) {
  $sync_field = profile_sync_email_instance_info();
  $profile = profile2_load_by_user($account, $sync_field->bundle);
  if ($profile) {
    if (isset($profile->{$sync_field->field_name}[LANGUAGE_NONE][0]['email'])) {
      $email = &$profile->{$sync_field->field_name}[LANGUAGE_NONE][0]['email'];
    } else {
      $email = '';
    }
    if (isset($edit['mail']) && $email != $edit['mail'] && !empty($edit['mail']) && (!isset($_SESSION['profile_sync_email_user']) || !$_SESSION['profile_sync_email_user'])) {
      $email = $edit['mail'];
  
      $_SESSION['profile_sync_email_user'] = TRUE; // set lock
      profile2_save($profile);
      $_SESSION['profile_sync_email_user'] = FALSE; // remove lock
    }
  } // if $profile
} // profile_sync_email_user()

/**
 * create a profile for the user
 */
function profile_sync_email_create_profile($user, $bundle) {
  // get the user profile
  $profile = profile2_load_by_user($user, $bundle);

  // if a profile exists, exit here
  if ($profile) return;

  // no profile exists, check for an anonymous profile with a matching email
  $sync_field = profile_sync_email_instance_info();
  $pid_query = db_select('profile', 'p')
    ->fields('p', array('pid'))
    ->condition('p.uid', 0)
    ->condition('fd.' . $sync_field->field_name . '_email', $user->mail);
  $pid_query->join('field_data_' . $sync_field->field_name, 'fd', 
    'fd.entity_id = p.pid AND fd.entity_type = :entity_type AND fd.bundle = :bundle', 
     array(':entity_type' => $sync_field->entity_type, ':bundle' => $sync_field->bundle));
  $pid = $pid_query->execute()->fetchField();
  if ($pid) {
    $profile = profile2_load($pid);
    $profile->uid = $user->uid;
    profile2_save($profile);
    return;
  }

  // build the profile
  $profile_values = array(
    'type' => $bundle,
    'uid' => $user->uid,
  );
  $fields = field_info_instances('profile2', $bundle);
  foreach (array_keys($fields) as $field_name) {
    $profile_values[$field_name] = array();
  }
  $profile = profile_create($profile_values);
  profile2_save($profile);
} // profile_sync_email_create_profile()
  

/**
 * helper function to return info about the sync field
 */
function profile_sync_email_instance_info() {
  $sync_field = variable_get('profile_sync_email_instance', -1);
  $instance_info = FALSE;
  if ($sync_field) {
    $instance_info = db_select('field_config_instance', 'fci')
      ->fields('fci', array('field_name', 'entity_type', 'bundle'))
      ->condition('id', $sync_field)
      ->execute()
      ->fetch();
  }
  return $instance_info;
} // profile_sync_email_instance_info()
