diff --git a/includes/d7.api.inc b/includes/d7.api.inc
new file mode 100644
index 0000000..511f9b0
--- /dev/null
+++ b/includes/d7.api.inc
@@ -0,0 +1,75 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Reimplement Drupal 7 API functions as needed.
+ */
+if (!function_exists('drupal_static')) {
+  /**
+   * Central static variable storage.
+   *
+   * @param $name
+   *   Globally unique name for the variable. For a function with only one static,
+   *   variable, the function name (e.g. via the PHP magic __FUNCTION__ constant)
+   *   is recommended. For a function with multiple static variables add a
+   *   distinguishing suffix to the function name for each one.
+   * @param $default_value
+   *   Optional default value.
+   * @param $reset
+   *   TRUE to reset a specific named variable, or all variables if $name is NULL.
+   *   Resetting every variable should only be used, for example, for running
+   *   unit tests with a clean environment. Should be used only though via
+   *   function drupal_static_reset() and the return value should not be used in
+   *   this case.
+   *
+   * @return
+   *   Returns a variable by reference.
+   *
+   * @see drupal_static_reset()
+   */
+  function &drupal_static($name, $default_value = NULL, $reset = FALSE) {
+    static $data = array(), $default = array();
+    // First check if dealing with a previously defined static variable.
+    if (isset($data[$name]) || array_key_exists($name, $data)) {
+      // Non-NULL $name and both $data[$name] and $default[$name] statics exist.
+      if ($reset) {
+        // Reset pre-existing static variable to its default value.
+        $data[$name] = $default[$name];
+      }
+      return $data[$name];
+    }
+    // Neither $data[$name] nor $default[$name] static variables exist.
+    if (isset($name)) {
+      if ($reset) {
+        // Reset was called before a default is set and yet a variable must be
+        // returned.
+        return $data;
+      }
+      // First call with new non-NULL $name. Initialize a new static variable.
+      $default[$name] = $data[$name] = $default_value;
+      return $data[$name];
+    }
+    // Reset all: ($name == NULL). This needs to be done one at a time so that
+    // references returned by earlier invocations of drupal_static() also get
+    // reset.
+    foreach ($default as $name => $value) {
+      $data[$name] = $value;
+    }
+    // As the function returns a reference, the return should always be a
+    // variable.
+    return $data;
+  }
+}
+
+if (!function_exists('drupal_static_reset')) {
+  /**
+   * Reset one or all centrally stored static variable(s).
+   *
+   * @param $name
+   *   Name of the static variable to reset. Omit to reset all variables.
+   */
+  function drupal_static_reset($name = NULL) {
+    drupal_static($name, NULL, TRUE);
+  }
+}
diff --git a/resource_conflict.admin.inc b/resource_conflict.admin.inc
new file mode 100644
index 0000000..c4f943a
--- /dev/null
+++ b/resource_conflict.admin.inc
@@ -0,0 +1,43 @@
+<?php
+
+/**
+ * Displays the admin settings form.
+ */
+function resource_conflict_admin_settings() {
+  return drupal_get_form('resource_conflict_admin_general');
+}
+
+function resource_conflict_admin_general(){
+  $form = array();
+
+  $form['resource_conflict_form_error'] = array(
+    '#type' => 'checkbox',
+    '#title' => '<strong>'. t('Display form errors on resource conflict enabled items.') .'</strong>',
+    '#description' => t('If this option is selected, resource conflict enabled items with display form errors on conflicts. If it is disabled the form will show a warning, but allow the conflict to schedule.'),
+    '#default_value' => variable_get('resource_conflict_form_error', TRUE),
+  );
+
+  if (module_exists('og')) {
+    $form['resource_conflict_og_aware'] = array(
+      '#type' => 'checkbox',
+      '#title' => '<strong>'. t('Restrict conflict checking to current OG when in a group.') .'</strong>',
+      '#description' => t('If this option is selected, resource conflict checking will be limited to resources posted in the current group (when in a group).'),
+      '#default_value' => variable_get('resource_conflict_og_aware', FALSE),
+    );
+  }
+
+  $form['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Save configuration'),
+  );
+
+  return $form;
+}
+
+function resource_conflict_admin_general_submit($form, &$form_state) {
+  variable_set('resource_conflict_form_error', $form_state['values']['resource_conflict_form_error']);
+  variable_set('resource_conflict_og_aware', $form_state['values']['resource_conflict_og_aware']);
+
+  drupal_set_message(t('Configuration saved.'));
+}
+
diff --git a/resource_conflict.install b/resource_conflict.install
index 518924f..fae3210 100644
--- a/resource_conflict.install
+++ b/resource_conflict.install
@@ -7,9 +7,15 @@
 function resource_conflict_uninstall() {
   _resource_conflict_variable_delete_like('rc_type_%');
   _resource_conflict_variable_delete_like('rc_date_field_%');
+  _resource_conflict_variable_delete_like('rc_repeat_type_%');
+  _resource_conflict_variable_delete_like('rc_av_enabled_%');
+  _resource_conflict_variable_delete_like('rc_repeat_field_%');
+  _resource_conflict_variable_delete_like('rc_views_%');
   _resource_conflict_variable_delete_like('rc_reference_fields_%');
-  
+
   variable_del('rc_types');
+  variable_del('rc_repeat_types');
+  variable_del('rc_av_types');
 }
 
 /**
@@ -17,7 +23,7 @@ function resource_conflict_uninstall() {
  */
 function resource_conflict_update_5200() {
   $ret = array();
-  
+
   // Rename all resource_conflict_$type variables to rc_type_$type
   $q = "SELECT name FROM {variable} WHERE name LIKE 'resource_conflict_%' AND name NOT LIKE 'resource_conflict_fields_%'";
   $result = db_query($q);
@@ -25,22 +31,22 @@ function resource_conflict_update_5200() {
     $type = str_replace('resource_conflict_', '', $row['name']);
     $q = "UPDATE {variable} SET name = 'rc_type_" . $type .  "' WHERE name = 'resource_conflict_" . $type . "'";
     $ret[] = update_sql($q);
-    
+
     // Also set the type to be event
     variable_set('rc_date_field_' . $type, 'event');
-    
+
     // Finally, rename the enabled fields for the type
     $q = "UPDATE {variable} SET name = 'rc_reference_fields_" . $type . "' WHERE name = 'resource_conflict_fields_" . $type . "'";
     $ret[] = update_sql($q);
   }
-  
+
   return $ret;
 }
 
 /**
  * Delete all variables matching a pattern using SQL 'LIKE' syntax.
  * @param $pattern
- *   The pattern of variables to delete. 
+ *   The pattern of variables to delete.
  */
 function _resource_conflict_variable_delete_like($pattern) {
   $q = "SELECT name FROM {variable} WHERE name LIKE '%s'";
diff --git a/resource_conflict.module b/resource_conflict.module
index 179cab9..9f2a738 100644
--- a/resource_conflict.module
+++ b/resource_conflict.module
@@ -1,6 +1,42 @@
 <?php
+// $Id: resource_conflict.module,v 1.6 2010/01/20 03:55:49 deviantintegral Exp $
 //VIM setup ex: et sw=2 ts=2 syntax=php
 
+// Re-implement needed Drupal 7 API functions in a seperate file.
+require_once dirname(__FILE__) . '/includes/d7.api.inc';
+
+/**
+ * Implementation of hook_perm().
+ */
+function resource_conflict_roles_perm() {
+  return array('administer resource conflict');
+}
+
+/**
+ * Implementation of hook_menu().
+ */
+function resource_conflict_menu(){
+  $items = array();
+
+  $items['admin/settings/resource-conflict'] = array(
+    'title' => 'Resource Conflict',
+    'description' => "Configure Resource Conflict settings.",
+    'access arguments' => array('administer resource conflict'),
+    'page callback' => 'resource_conflict_admin_settings',
+    'type' => MENU_NORMAL_ITEM,
+    'file' => 'resource_conflict.admin.inc',
+  );
+
+  $items['rc_availability/check'] = array(
+    'title' => 'Ahah Availability Callback',
+    'access callback' => TRUE,
+    'page callback' => 'resource_conflict_ahah_availability',
+    'type' => MENU_CALLBACK,
+  );
+
+  return $items;
+}
+
 /**
  * Implementation of hook_nodeapi
  *
@@ -8,17 +44,18 @@
  */
 function resource_conflict_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
   switch ($op) {
-    case 'validate':
-      $type = $node->type;
-      if (!variable_get('rc_type_' . $type, FALSE)) {
-        // Conflict handling is not enabled for this node.
-        break;
-      }
-
+  case 'validate':
+    $type = $node->type;
+    if (!variable_get('rc_type_' . $type, FALSE)) {
+      // Conflict handling is not enabled for this node.
+      // break;
+    }
+    else {
       // Find the date field to use for time overlapping_node_ids detection.
       $date_field = variable_get('rc_date_field_' . $type, FALSE);
 
       $overlapping_node_ids = array();
+      $overlapping_availability_node_ids = array();
 
       if (strpos($date_field, 'field_', 0) === 0) {
         // Get the start and end Date of the current node
@@ -27,7 +64,15 @@ function resource_conflict_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
 
         // Get all conflicting Date nodes
         if (!empty($start) && !empty($end)) {
-          $overlapping_node_ids = _resource_conflict_overlaps_from_date($start, $end);
+          $time_spans_raw = array();
+          foreach ($node->{$date_field} as $single_repetition_date) {
+            $time_spans_raw[] = array(
+              'start' => $single_repetition_date['value'],
+              'end' => $single_repetition_date['value2'],
+            );
+          }
+          $overlapping_node_ids = _resource_conflict_overlaps_from_date($time_spans_raw);
+          $overlapping_availability_node_ids = _resource_availability_overlaps_from_date($node, $time_spans_raw);
         }
         else {
           // If we got here, someone broke the requirements, so turn off
@@ -39,6 +84,8 @@ function resource_conflict_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
         // Get all overlapping events
         $tmp = _resource_conflict_overlaps_from_event($node->event_start, $node->event_end);
         $overlapping_node_ids = array_unique(array_merge($overlapping_node_ids, $tmp));
+        $tmp2 = _resource_availability_overlaps_from_event($node, $node->event_start, $node->event_end);
+        $overlapping_availability_node_ids = array_unique(array_merge($overlapping_availability_node_ids, $tmp2));
       }
 
       // Load conflicting nodes
@@ -52,12 +99,64 @@ function resource_conflict_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
 
       // Display conflict errors
       _resource_conflict_display_conflict_errors($node, $conflicting_nodes);
-      break;
+
+      // Display availability errors
+      _resource_conflict_display_availability_errors($node, $overlapping_availability_node_ids);
+    }
+    break;
+  case 'presave':
+    $conflict_types = _resource_conflict_get_conflict_enabled_types();
+    if (in_array($node->type, $conflict_types)) {
+      resource_conflict_invalidate_cache();
+    }
   }
 }
 
 
 /**
+ * Compare our demand to the availability on the resource
+ * and display errors for no intersections
+ *
+ * @param $node the currently validating node
+ * @param $overlapping_availability_node_ids array of node and delta that have availability with this node
+ */
+function _resource_conflict_display_availability_errors($node, $overlapping_availability_node_ids) {
+  $availability_types = _resource_conflict_get_availability_enabled_types();
+  $availability_check = FALSE;
+
+  foreach (_resource_conflict_get_node_resource_demand($node) as $nid=>$dummy) {
+    $noderef = node_load($nid);
+    $availability_check = TRUE;
+    foreach ($availability_types as $availability_type) {
+      // is the availability set on this type
+      $availability_check = $availability_check && variable_get('rc_av_enabled_' . $noderef->type, '0');
+    }
+  }
+
+  $field_name = variable_get('rc_date_field_' . $node->type,'');
+  $error = t("There are no available time slots on the resource for the time span you have requested.");
+  // if admin enabled the ability for users to check - and did the user enable force non-overlapping
+  if (!count($overlapping_availability_node_ids) && $availability_check) {
+    if (variable_get('resource_conflict_form_error', TRUE)) {
+      $error_id = 'availability_error' . $node->nid;
+      form_set_error($error_id, $error);
+    }
+    else {
+      drupal_set_message($error, 'warning');
+    }
+  }
+
+  // in case of date repeat, we have to make sure that all timespans are satisfied
+  $date_field = variable_get('rc_date_field_'. $node->type, FALSE);
+  $rows_demanded = $node->{$date_field};
+  if ((count($overlapping_availability_node_ids) > 0) && count($rows_demanded) > count($overlapping_availability_node_ids && $availability_check)) {
+    $error = t("There are some timespans in which some of the resources weren't available. Try to reduce the date repeat period.");
+    $error_id = 'availability_error' . $node->nid;
+    form_set_error($error_id, $error);
+  }
+}
+
+/**
  * Compare our demand to the demand of overlapping nodes
  * and display errors for the intersections
  *
@@ -81,9 +180,9 @@ function _resource_conflict_display_conflict_errors($node, $conflicting_nodes) {
     foreach ($conflicting_resources as $conflicting_resource) {
       $date_field = variable_get('rc_date_field_'. $conflicting_node->type, FALSE);
       if (strpos($date_field, 'field_', 0) === 0) {
-        $type = DATE_ISO;
+                $type = DATE_ISO;
         // If date_start is not in DATE_ISO set the type to DATE_DATETIME.
-        if (!date_is_valid($date_start,DATE_ISO)) {
+        if (!_resource_conflict_date_is_valid($date_start,DATE_ISO)) {
           $type = DATE_DATETIME;
         }
 
@@ -105,7 +204,6 @@ function _resource_conflict_display_conflict_errors($node, $conflicting_nodes) {
           '%end' => $end,
         )
       );
-
       // This is a bit of a hack, but there's no way with FAPI to have
       // multiple form errors on the same field.  So, we just pass in
       // a bogus (but unique) ID for each error message, to ensure
@@ -113,7 +211,13 @@ function _resource_conflict_display_conflict_errors($node, $conflicting_nodes) {
       // nid of the conflicting resource (thing) appended with the nid
       // of the conflicting node (reservation event).
       $conflict_id = $conflicting_resource->nid . '_' . $conflicting_node->nid;
-      form_set_error($conflict_id, $error);
+
+      if( variable_get('resource_conflict_form_error', TRUE) ) {
+        form_set_error($conflict_id, $error);
+      }
+      else {
+        drupal_set_message($error, 'warning');
+      }
     }
   }
 }
@@ -144,6 +248,7 @@ function resource_conflict_form_alter(&$form, $form_state, $form_id) {
     }
 
     $date_fields = array();
+    $date_repeat_fields = array();
     if ($type != NULL) {
       $type_info = content_types($type);
       $fields = $type_info['fields'];
@@ -152,9 +257,12 @@ function resource_conflict_form_alter(&$form, $form_state, $form_id) {
         if ($field['type'] == 'nodereference') {
           $nodereference_fields[$field['field_name']] = $field['widget']['label'];
         }
-        elseif (($field['type'] == 'date' || $field['type'] == 'datetime') && $field['todate'] == 'required' && $field['required']) {
+        elseif (($field['type'] == 'date' || $field['type'] == 'datetime') && $field['todate'] == 'required' && $field['required'] && !$field['repeat']) {
           $date_fields[$field['field_name']] = $field['widget']['label'];
         }
+        elseif ($field['type'] == 'date' && $field['todate'] == 'required' && $field['required'] && $field['repeat']){
+          $date_repeat_fields[$field['field_name']] = $field['widget']['label'];
+        }
       }
     }
 
@@ -174,7 +282,7 @@ function resource_conflict_form_alter(&$form, $form_state, $form_id) {
       $date_fields += array('event' => t('Use Event Field from the Event Module'));
     }
 
-    if (empty($date_fields) && !$event_enabled) {
+    if (empty($date_fields) && empty($date_repeat_fields) && !$event_enabled) {
       if (module_exists('event')) {
         $requirements['event'] = t('This content type is not event enabled. Please event-enable this content type if you wish to use Resource Conflict with the Event module.');
       }
@@ -185,6 +293,13 @@ function resource_conflict_form_alter(&$form, $form_state, $form_id) {
       $requirements['date_api'] = t('This content type does not contain any suitable Date fields. Please add at least one Date field with required start and end dates if you wish to use Resource Conflict with the Date module.');
     }
 
+    if (empty($date_repeat_fields)){
+      $availability_requirements['date_repeat'] = t('This content type contains no date repeat field - which can be used to restrict what times the resource to check conflicts only during availability.');
+    }
+    if (!module_exists('views')) {
+      $availability_requirements['views'] = t('You can use the <strong>views module</strong> to specify a view that would return needed nodes (advanced) -  which contain date fields that can be used to restrict the resources.');
+    }
+
     if (!empty($requirements)) {
       _resource_conflict_disable($type, TRUE);
 
@@ -212,7 +327,7 @@ function resource_conflict_form_alter(&$form, $form_state, $form_id) {
       $form['resource_conflict_set']['rc_date_field'] = array(
         '#type' => 'select',
         '#title' => t('Field to use as the date for conflict checks'),
-        '#options' => $date_fields,
+        '#options' => array_merge($date_fields, $date_repeat_fields),
         '#multiple' => FALSE,
         '#default_value' => variable_get('rc_date_field_' . $type, FALSE),
         '#description' => t("Select the date field to use to check for resource conflicts."),
@@ -227,29 +342,159 @@ function resource_conflict_form_alter(&$form, $form_state, $form_id) {
       );
     }
 
-    //set custom validation and submit callbacks
+    // Create the fieldset for availability and all the related things
+    $form['resource_conflict_set']['rc_availability'] = array(
+      '#type' => 'fieldset',
+      '#title' => 'Availability settings',
+      '#description' => t('If you consider this to be a resource, specify if you wish to use the availability.'),
+      '#collapsible' => TRUE,
+    );
+    if (!empty($availability_requirements)) {
+      $form['resource_conflict_set']['rc_availability']['availability_requirements'] = array(
+        '#prefix' => '<p>' . t('To enable <strong>availability</strong> make sure:') . '</p><ul>',
+        '#suffix' => '</ul>',
+        '#weight' => -10,
+      );
+      foreach ($availability_requirements as $component => $error) {
+        $form['resource_conflict_set']['rc_availability']['availability_requirements'][$component] = array(
+          '#prefix' => '<li>',
+          '#suffix' => '</li>',
+          '#value' => $error,
+        );
+      }
+    }
+
+    // If at least 1 requierement was met (one option available) we enable the checkbox
+    if (count($availability_requirements) < 2) {
+      $enable_availability = TRUE;
+    }
+    else {
+      $enable_availability = FALSE;
+    }
+
+    $form['resource_conflict_set']['rc_availability']['rc_av_enabled'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Enable availability'),
+      '#description' => t('Enable availability resource conflict checking for this content type'),
+      '#default_value' => variable_get('rc_av_enabled_' . $type, 0),
+      '#weight' => -8,
+      '#disabled' => !$enable_availability,
+      '#ahah' => array(
+        'path' => 'rc_availability/check',
+        'wrapper' => 'rc_availability',
+        'effect' => 'fade',
+      ),
+      '#suffix' => (!variable_get('rc_av_enabled_' . $type, 0)) ? '<div id="rc_availability"></div>': '',
+    );
+
+    if (variable_get('rc_av_enabled_' . $type, 0) || $form_state['values']['rc_av_enabled']) {
+      if (!isset($availability_requirements['date_repeat'])) {
+        $form['resource_conflict_set']['rc_availability']['rc_repeat_field'] = array(
+          '#type' => 'select',
+          '#title' => t('Resource Availablity'),
+          '#options' => array_merge(array('0' => '- DISABLED - '), $date_repeat_fields),
+          '#default_value' => variable_get('rc_repeat_field_' . $type, '0'),
+          '#description' => t("Select the repeat field to use to allocate availability on a resource."),
+        );
+      }
+      if (!isset($availability_requirements['views'])) {
+        // We get all the views via this function because some of those can be stored in the code
+        $views = views_get_all_views();
+        $views_keys = array_keys($views);
+        $views_val = array();
+        foreach($views_keys as $key) {
+          $views_val[$key] = $key;
+        }
+        $form['resource_conflict_set']['rc_availability']['rc_views'] = array(
+          '#type' => 'select',
+          '#title' => t('Views available'),
+          '#options' => array_merge(array('0' => '- DISABLED -'), $views_val),
+          '#default_value' => variable_get('rc_views_' . $type, '0'),
+          '#description' => t("Specify a view that you wish to use."),
+        );
+      }
+    }
+    // setup the wrapper properly
+    if (count($availability_requirements) == 2) {
+      $form['resource_conflict_set']['rc_availability']['rc_av_enabled']['#suffix'] = '<div id="rc_availability"></div>';
+    }
+    else {
+      if (empty($availability_requirements)) {
+        $form['resource_conflict_set']['rc_availability']['rc_repeat_field']['#prefix'] = '<div id="rc_availability">';
+        $form['resource_conflict_set']['rc_availability']['rc_views']['#suffix'] = '</div>';
+      }
+      else if (!isset($availability_requirements['date_repeat'])) {
+        $form['resource_conflict_set']['rc_availability']['rc_repeat_field']['#prefix'] = '<div id="rc_availability">';
+        $form['resource_conflict_set']['rc_availability']['rc_repeat_field']['#suffix'] = '</div>';
+      }
+      else if (!isset($availability_requirements['views'])) {
+        $form['resource_conflict_set']['rc_availability']['rc_views']['#prefix'] = '<div id="rc_availability">';
+        $form['resource_conflict_set']['rc_availability']['rc_views']['#suffix'] = '</div>';
+      }
+
+    }
+
+    // set custom validation and submit callbacks
     $form['#validate'][] = 'resource_conflict_form_validate';
     $form['#submit'][] = 'resource_conflict_form_submit';
+
+    // if the form action change, restore the old one. (it gets change via ahah + validation)
+    if (isset($form_state['storage']['old_action']) &&
+        ($form['#action'] != $form_state['storage']['old_action'])) {
+      $form['#action'] = $form_state['storage']['old_action'];
+    }
   }
 }
 
 /**
  * Validate the node_type_form
  */
-function resource_conflict_form_validate($form, &$form_state) {
+function resource_conflict_form_validate(&$form, &$form_state) {
   if ($form_state['values']['form_id'] == 'node_type_form') {
+    // Check if a resource was selected *when* rc was enabled
     if ($form_state['values']['rc_type']) {
       $resource_selected = FALSE;
+
       foreach ($form_state['values']['rc_reference_fields'] as $field) {
         if ($field) {
           $resource_selected = TRUE;
           break;
         }
       }
+
       if (!$resource_selected) {
         form_set_error('rc_reference_fields', t("At least one resource field must be set if conflict handling is enabled."));
       }
     }
+
+    // Check if an availability option was chosen *when* availability was enabled
+    if (isset($form_state['values']['rc_av_enabled']) && $form_state['values']['rc_av_enabled'] && !$form_state['ahah_submission']) {
+      $availability_selected = FALSE;
+      // check if user selected any value in those fields
+      if ($form_state['values']['rc_repeat_field'] || $form_state['values']['rc_views']) {
+        $availability_selected = TRUE;
+        // check if user selected both resources
+        if ($form_state['values']['rc_repeat_field'] && !($form_state['values']['rc_repeat_field'] == '0') && $form_state['values']['rc_views']  && !($form_state['values']['rc_views'] == '0')) {
+          $double_availability = TRUE;
+        } else {
+          $double_availability = FALSE;
+        }
+      }
+      if (!$availability_selected) {
+        form_set_error('rc_availability', t("Please make sure at least one of option is selected."));
+      }
+      if ($double_availability) {
+        form_set_error('rc_availability', t("Please make sure only one of those options are selected (date repeat or views)."));
+      }
+    }
+    else {
+      // if user disabled availability delete the old variable values
+      $type = (isset($form['old_type']) && isset($form['old_type']['#value'])) ? $form['old_type']['#value'] : NULL;
+      if ($type) {
+        variable_del('rc_repeat_field_' . $type);
+        variable_del('rc_views_' . $type);
+      }
+    }
   }
 }
 
@@ -257,22 +502,75 @@ function resource_conflict_form_validate($form, &$form_state) {
  * Submit the node_type_form
  */
 function resource_conflict_form_submit($form, &$form_state) {
-  $type = $form_state['values']['type'];
-  $old_type = $form_state['values']['old_type'];
-  $conflict_types = variable_get("rc_types", array());
+  // case of availability on
+  if ($form_state['values']['rc_av_enabled']) {
+    $type = $form_state['values']['type'];
+    $old_type = $form_state['values']['old_type'];
+    $av_types = variable_get("rc_av_types", array());
+
+    //unset old entry
+    if (!empty($old_type)) {
+      $key = array_search($old_type, $av_types);
+      unset($av_types[$key]);
+    }
 
-  //unset old entry
-  if (!empty($old_type)) {
-    $key = array_search($old_type, $conflict_types);
-    unset($conflict_types[$key]);
+    $av_types[] = $type;
+    variable_set("rc_av_types", $av_types);
   }
+  else {
+    $type = $form_state['values']['type'];
+    $old_type = $form_state['values']['old_type'];
+    $conflict_types = variable_get("rc_types", array());
 
-  //make new entry if this type is conflict handled
-  if ($form_state['values']['rc_type']) {
-    $conflict_types[] = $type;
+    //unset old entry
+    if (!empty($old_type)) {
+      $key = array_search($old_type, $conflict_types);
+      unset($conflict_types[$key]);
+    }
+
+    //make new entry if this type is conflict handled
+    if ($form_state['values']['rc_type']) {
+      $conflict_types[] = $type;
+    }
+
+    variable_set("rc_types", $conflict_types);
+  }
+}
+
+/*
+ * AHAH Callback for availability
+ */
+function resource_conflict_ahah_availability() {
+  module_load_include('inc', 'node', 'content_types');
+  $form_state = array('storage' => NULL, 'submitted' => FALSE);
+  $form_build_id = $_POST['form_build_id'];
+  $form = form_get_cache($form_build_id, $form_state);
+  $args = $form['#parameters'];
+  $form_id = array_shift($args);
+  $form_state['post'] = $form['#post'] = $_POST;
+  // Enable the submit/validate handlers to determine whether AHAH-submittted.
+  $form_state['ahah_submission'] = TRUE;
+  $form['#programmed'] = $form['#redirect'] = FALSE;
+
+  // Trick to remember the old action
+  $form['#cache'] = TRUE;
+
+  // When not set.. try to remember the old action
+  if (!isset($form_state['storage']['old_action'])) {
+    $form_state['storage']['old_action'] = isset($form['#action']) ? $form['#action'] : $_GET['q'];
   }
 
-  variable_set("rc_types", $conflict_types);
+  drupal_process_form($form_id, $form, $form_state);
+  $form = drupal_rebuild_form($form_id, $form_state, $args, $form_build_id);
+
+
+  $output = theme('status_messages');
+  $output .= drupal_render($form['resource_conflict_set']['rc_availability']['rc_repeat_field']);
+  $output .= drupal_render($form['resource_conflict_set']['rc_availability']['rc_views']);
+
+  // Final rendering callback.
+  drupal_json(array('status' => TRUE, 'data' => $output));
+  exit();
 }
 
 /**
@@ -285,6 +583,16 @@ function _resource_conflict_get_conflict_enabled_types() {
   $conflict_types = variable_get("rc_types", array());
   return $conflict_types;
 }
+/**
+ * Get the conflict enabled types
+ *
+ * @return
+ *   An array of type names
+ */
+function _resource_conflict_get_availability_enabled_types() {
+  $availability_types = variable_get("rc_av_types", array());
+  return $availability_types;
+}
 
 /**
  * Get a conflict enabled node's resource demand
@@ -323,6 +631,51 @@ function _resource_conflict_get_node_resource_demand($node) {
 /**
  * Determine if any nodes conflict between the specified dates using Date API.
  *
+ * @param $time_spans_input
+ *   An array of 'time span' arrays. Each array has the following keys:
+ *   - start: An ISO timestamp representing the start of the time span.
+ *   - end:  An ISO timestamp representing the end of the time span.
+ * @return
+ *   An array of node ID's.
+ */
+function _resource_conflict_overlaps_from_date($time_spans_input) {
+  $time_spans = array();
+  foreach ($time_spans_input as $single_time_span_input) {
+    // Make the default type to DATE_ISO.
+    $type = DATE_ISO;
+    // If date_start is not in DATE_ISO set the type to DATE_DATETIME.
+    if (!_resource_conflict_date_is_valid($single_time_span_input['start'], DATE_ISO)) {
+      $type = DATE_DATETIME;
+    }
+
+       $time_spans[] = array(
+      'start' => date_make_date($single_time_span_input['start'], 'GMT', $type),
+      'end' => date_make_date($single_time_span_input['end'], 'GMT', $type),
+    );
+  }
+  return _resource_conflict_get_overlaps($time_spans);
+}
+/**
+ * Determine if any nodes conflict between the specified dates using Event.
+ *
+ * @param $event_start
+ *   The start date of the event to check
+ * @param $event_end
+ *   The end date of the event to check.
+ * @return
+ *   An array of node ID's
+ */
+function _resource_availability_overlaps_from_event($node, $event_start, $event_end) {
+  $start = date_make_date($event_start, 'GMT', DATE_UNIX);
+  $end = date_make_date($event_end, 'GMT', DATE_UNIX);
+  return _resource_availability_overlaps($node, array(array('start' => $start, 'end' => $end)));
+}
+
+
+
+/**
+ * Determine if the selected event falls within the availablity between the specified dates using Date API.
+ *
  * @param $date_start
  *   The start date of the date to check
  * @param $date_end
@@ -330,19 +683,25 @@ function _resource_conflict_get_node_resource_demand($node) {
  * @return
  *   An array of node ID's
  */
-function _resource_conflict_overlaps_from_date($date_start, $date_end) {
-  // Make the default type to DATE_ISO.
-  $type = DATE_ISO;
-  // If date_start is not in DATE_ISO set the type to DATE_DATETIME.
-  if (!date_is_valid($date_start,DATE_ISO)) {
-    $type = DATE_DATETIME;
-  }
+function _resource_availability_overlaps_from_date($node, $time_spans_input) {
+  $time_spans = array();
+  foreach ($time_spans_input as $single_time_span_input) {
+    // Make the default type to DATE_ISO.
+    $type = DATE_ISO;
+    // If date_start is not in DATE_ISO set the type to DATE_DATETIME.
+    if (!_resource_conflict_date_is_valid($single_time_span_input['start'], DATE_ISO)) {
+      $type = DATE_DATETIME;
+    }
 
-  $start = date_make_date($date_start, 'GMT', $type);
-  $end = date_make_date($date_end, 'GMT', $type);
-  return _resource_conflict_get_overlaps($start, $end);
+       $time_spans[] = array(
+      'start' => date_make_date($single_time_span_input['start'], 'GMT', $type),
+      'end' => date_make_date($single_time_span_input['end'], 'GMT', $type),
+    );
+  }
+  return _resource_availability_overlaps($node, $time_spans);
 }
 
+
 /**
  * Determine if any nodes conflict between the specified dates using Event.
  *
@@ -356,7 +715,7 @@ function _resource_conflict_overlaps_from_date($date_start, $date_end) {
 function _resource_conflict_overlaps_from_event($event_start, $event_end) {
   $start = date_make_date($event_start, 'GMT', DATE_UNIX);
   $end = date_make_date($event_end, 'GMT', DATE_UNIX);
-  return _resource_conflict_get_overlaps($start, $end);
+  return _resource_conflict_get_overlaps(array(array('start' => $start, 'end' => $end)));
 }
 
 /**
@@ -366,68 +725,297 @@ function _resource_conflict_overlaps_from_event($event_start, $event_end) {
  * 2. $end end is within the event time
  * 3. The event encompasses $start and $end
  * 4. Allow the end of one event to occur at the start of the next
- * 
- * @param $start
- *   The start time of events to search as dateAPI object
- * @param $end
- *   The end time of events to search as dateAPI object
+ *
+ * @param $time_spans
+ *   An array of 'time span' arrays with the following keys:
+ *   - start: A Date API object representing the start of the time span.
+ *   - end:  A Date API object representing the end of the time span.
+ *   Each 'time span' array has a 'start' and an 'end' key and dateAPI objects as values.
  * @return
  *   An array of node ID's
  */
-function _resource_conflict_get_overlaps($start, $end) {
-  $date_start = date_convert($start, DATE_OBJECT, DATE_ISO);
-  $date_end = date_convert($end, DATE_OBJECT, DATE_ISO);
-  $event_start = date_convert($start, DATE_OBJECT, DATE_UNIX);
-  $event_end = date_convert($end, DATE_OBJECT, DATE_UNIX);
+function _resource_conflict_get_overlaps($time_spans) {
+  static $warm_cache = FALSE;
+  $cache = &drupal_static(__FUNCTION__, array());
+
+  if (!$warm_cache) {
+    $warm_cache = TRUE;
+    $drupal_cache = cache_get('_resource_conflict_get_overlaps');
+    if ($drupal_cache) {
+      $cache = $drupal_cache->data;
+    }
+  }
 
   $rows = array();
   $conflict_types = _resource_conflict_get_conflict_enabled_types();
 
+  // Determine if we have an OG context
+  if (variable_get('resource_conflict_og_aware', FALSE) && module_exists('og') && $group = og_determine_context()) {
+    $og_nid = $group->nid;
+  } else {
+    $og_nid = FALSE;
+  }
+
   foreach ($conflict_types as $type) {
     $date_field = variable_get('rc_date_field_' . $type, FALSE);
 
     if(strpos($date_field, 'field_', 0) === 0) {
+      $str_span = serialize($time_spans);
+      $hash = md5($str_span);
+      $cid = ($og_nid?$og_nid.':':'').$hash;
+      if (isset($cache[$cid])) {
+        return $cache[$cid];
+      }
+
       $date_db_info = content_database_info(content_fields($date_field));
       $date_table = '{' . $date_db_info['table'] . '}';
 
       $start_field_name = $date_db_info['columns']['value']['column'];
       $end_field_name = $date_db_info['columns']['value2']['column'];
 
+      $start_field_type = DATE_ISO;
+      if ($date_db_info['columns']['value']['type'] == 'datetime') {
+        $start_field_type = DATE_DATETIME;
+      }
+      // Make SQL OG-aware
+      if ($og_nid) {
+        $og_join = "LEFT JOIN {og_ancestry} ON date_table.nid = {og_ancestry}.nid";
+        $og_where = "AND (group_nid = $og_nid OR group_nid IS NULL)";
+      } else {
+        $og_join = '';
+        $og_where = '';
+      }
+
+      $where_or = array();
+      $query_args = array();
+      foreach ($time_spans as $time_span) {
+        $date_start = date_convert($time_span['start'], DATE_OBJECT, $start_field_type);
+        $date_end = date_convert($time_span['end'], DATE_OBJECT, $start_field_type);
+
+        $where_or[] = "('%s' >= date_table.$start_field_name AND '%s' < date_table.$end_field_name)";
+        $query_args[] = $date_start;
+        $query_args[] = $date_start;
+
+        $where_or[] = "('%s' > date_table.$start_field_name AND '%s' <= date_table.$end_field_name)";
+        $query_args[] = $date_end;
+        $query_args[] = $date_end;
+
+        $where_or[] = "('%s' <= date_table.$start_field_name AND '%s' >= date_table.$end_field_name)";
+        $query_args[] = $date_start;
+        $query_args[] = $date_end;
+      }
+
       $query = "SELECT DISTINCT {node}.nid FROM {node} INNER JOIN $date_table date_table ON {node}.vid = date_table.vid
-        WHERE('%s' >= date_table.$start_field_name AND '%s' < date_table.$end_field_name)
-        OR('%s' > date_table.$start_field_name AND '%s' <= date_table.$end_field_name)
-        OR('%s' <= date_table.$start_field_name AND '%s' >= date_table.$end_field_name)";
+      " . $og_join . "
+        WHERE " . implode(' OR ', $where_or) . " " . $og_where;
+      $query .= " ORDER BY date_table.$start_field_name";
 
-      $result = db_query($query, $date_start, $date_start, $date_end, $date_end, $date_start, $date_end);
+      $result = db_query($query, $query_args);
 
       // Create an array of all of the results
       while ($row = db_fetch_array($result)) {
         $rows[] = $row['nid'];
       }
+      $cache[$cid] = array_unique($rows);
     }
     elseif ($date_field == 'event') { //event enabled
-      $query = "SELECT DISTINCT nid FROM {event} WHERE (%d >= event_start AND %d < event_end)
+ $event_start = date_convert($time_spans[0]['start'], DATE_OBJECT, DATE_UNIX);
+      $event_end = date_convert($time_spans[0]['end'], DATE_OBJECT, DATE_UNIX);
+      $cid = "event:$event_start-$event_end";
+      if (isset($cache[$cid])) {
+        return $cache[$cid];
+      }
+
+      // Make SQL OG-aware
+      if ($og_nid) {
+        $og_join = "LEFT JOIN {og_ancestry} ON {event}.nid = {og_ancestry}.nid";
+        $og_where = "AND (group_nid = $og_nid OR group_nid IS NULL)";
+      } else {
+        $og_join = '';
+        $og_where = '';
+      }
+
+      $query = "SELECT DISTINCT nid FROM {event} $og_sql WHERE ((%d >= event_start AND %d < event_end)
         OR (%d > event_start AND %d <= event_end)
-        OR (%d <= event_start AND %d >= event_end)";
+        OR (%d <= event_start AND %d >= event_end)) $og_where";
       $result = db_query($query, $event_start, $event_start, $event_end, $event_end, $event_start, $event_end);
 
       // Create an array of all of the results
       while($row = db_fetch_array($result)) {
         $rows[] = $row['nid'];
       }
+      $cache[$cid] = array_unique($rows);
+    }
+    else {
+      return FALSE;
     }
   }
+  return $cache[$cid];
+}
+
+/**
+ * Determine if the event created falls within any of the available times on the resource
+ *
+ * 1. $start is within the event time
+ * 2. $end end is within the event time
+ * 3. The event encompasses $start and $end
+ * 4. Allow the end of one event to occur at the start of the next
+ *
+ * @param $start
+ *   The start time of events to search as dateAPI object
+ * @param $end
+ *   The end time of events to search as dateAPI object
+ * @return
+ *   An array of node ID's
+ */
+function _resource_availability_overlaps($node, $time_spans) {
+  $rows = array();
+  $availability_types = _resource_conflict_get_availability_enabled_types();
+  foreach (_resource_conflict_get_node_resource_demand($node) as $nid=>$dummy) {
+    $noderef = node_load($nid);
+    $uses_av = variable_get('rc_av_enabled_' . $noderef->type, FALSE);
+    // we check if the referenced resource is enabled or not
+    if (in_array($noderef->type, $availability_types) && $uses_av) {
+      _resource_availability_get_availability_rows($rows, $noderef, $time_spans);
+    }
+  }
+
   return array_unique($rows);
 }
 
 /**
+ * Returns the availability rows for a given node.
+ *
+ * @param <type> $rows
+ * @param <type> $node
+ * @param <type> $date_start
+ * @param <type> $date_end
+ * @param <type> $event_start
+ * @param <type> $event_end
+ */
+function _resource_availability_get_availability_rows(&$rows, $node, $time_spans) {
+  $avail_reference_field = variable_get('rc_repeat_field_' . $node->type, '0');
+  $avail_view = variable_get('rc_views_' . $node->type, '0');
+
+  // get rows according to the selected av type
+  if ($avail_reference_field) {
+    foreach($node->$avail_reference_field as $avail) {
+      // If this is a node reference...
+      if (isset($avail['nid'])) {
+        _resource_availability_get_availability_rows($rows, node_load($avail['nid']), $time_spans);
+      }
+      else {
+        foreach($time_spans as $time_span) {
+          if (($time_span['start']->format(DATE_FORMAT_ISO) >= $avail['value']) && ($time_span['end']->format(DATE_FORMAT_ISO) <= $avail['value2'])) {
+            $rows[] = $avail;
+          }
+          elseif (($time_span['start']->getTimestamp() >= date_convert($avail['value'], DATE_ISO, DATE_UNIX)) && ($time_span['end']->getTimestamp() <= date_convert($avail['value2'], DATE_ISO, DATE_UNIX))) {
+            $rows[] = $avail;
+          }
+        }
+      }
+    }
+  }
+  else if ($avail_view) {
+    module_load_include('inc', 'content', 'includes/content.crud');
+
+    // Get the view and needed fields, try to keep as generic as possible
+    $view = views_get_view($avail_view);
+
+    // Allow other users to change the view or to specify displays if they wish to
+    $display_id = NULL;
+
+    $data = array($node);
+    $data['__drupal_alter_by_ref'] = array(&$view, &$display_id);
+    drupal_alter('resource_conflict_view', $data);
+
+    // Identify needed fields
+    if ($display_id) {
+      $view->set_display($display_id);
+    }
+    else {
+      $display_id = 'default';
+    }
+    $view_fields = $view->get_items('field', $display_id);
+	$view_relationships = $view->get_items('relationship', $display_id);
+
+    // pass over all fields and get their handlers and name of the fields in results
+    $has_date = FALSE;
+    $date_fields = array();
+    foreach ($view_fields as $field) {
+      $handler = views_get_handler($field['table'], $field['field'], 'field');
+      if (get_class($handler) == 'date_handler_field_multiple') {
+        $has_date = TRUE;
+		// As a rule, date module uses fields as XXXX_value for start value and XXXX_value2 for end value
+        $date_fields[] = array(
+			'start' => $field['table'] . '_' . $field['field'],
+			'end' => $field['table'] . '_' . $field['field'] . '2'
+		);
+      }
+    }
+	// allow other users to specify custom field names
+	// because there are some weird cases when views doesn't
+	// follow the XXX_value and XXX_value2 rule
+
+    drupal_alter('resource_conflict_view_fields', &$date_fields);
+
+    // Get the results
+    $rows = array();
+
+    if (is_string($display_id)) {
+      $view->set_display($display_id);
+    }
+    else {
+      $view->init_display();
+    }
+    $view->pre_execute();
+    $view->execute();
+    $view_results = $view->result;
+
+    if (!$has_date || !$view_results || !$date_fields) {
+      return;
+    }
+    foreach ($view_results as $result) {
+	  // In some weird cases the NID of the field has this form
+	  $nid_name = (isset($result->nid)) ? 'nid' : 'node_node_data_' . key($view_relationships);
+
+      foreach($date_fields as $field) {
+        $start = $result->{$field['start']};
+        $end = $result->{$field['end']};
+        if (!$end) continue;
+
+        $date_startRow = $start;
+        $date_endRow = $end;
+        $event_startRow = date_convert($start, DATE_ISO, DATE_UNIX);
+        $event_endRow = date_convert($end, DATE_ISO, DATE_UNIX);
+
+		//$gmt = new DateTimeZone('GMT');
+        foreach($time_spans as $time_span) {
+		  // These dates are already in GMT
+		  //$time_span['start']->setTimezone($gmt);
+		  //$time_span['end']->setTimezone($gmt);
+
+          if (($time_span['start']->format(DATE_FORMAT_ISO) >= $date_startRow) && ($time_span['end']->format(DATE_FORMAT_ISO) <= $date_endRow)) {
+            $rows[] = $result->{$nid_name};
+          }
+          elseif (($time_span['start']->getTimestamp() >= $event_startRow) && ($time_span['end']->getTimestamp() <= $event_endRow)) {
+            $rows[] = $result->{$nid_name};
+          }
+        }
+      }
+    }
+  }
+}
+
+
+/**
  * Disable resource conflict for a type, optionally notifying the user. A
  * message is always logged in the Drupal log. If the content type is not
  * conflict-enabled, nothing is changed.
- * 
+ *
  * @param $type
  *  The content type to disable.
- *  
+ *
  * @param $display
  *   If TRUE, display the message with drupal_set_message().
  */
@@ -463,3 +1051,54 @@ if (!function_exists('date_show_value')) {
   }
 }
 
+/**
+ * Invalidate resource_conflict caches().
+ */
+function resource_conflict_invalidate_cache() {
+  // Reset static cache.
+  $caches = array(
+    '_resource_conflict_get_overlaps',
+  );
+
+  foreach ($caches as $cache) {
+    drupal_static_reset($cache);
+    cache_clear_all($cache, 'cache');
+  }
+}
+
+/**
+ * Implementation of hook_exit().
+ */
+function resource_confict_exit() {
+  $cache = &drupal_static('_resource_conflict_get_overlaps');
+  if (!empty($cache)) {
+    cache_set('_resource_conflict_get_overlaps', $cache, 'cache', CACHE_TEMPORARY);
+  }
+}
+
+
+/**
+ *  This function exists to work around a bug in date_is_valid as described in
+ *  http://drupal.org/node/792012
+ *
+ *  The date_is_valid tests the validity of a date in various formats.
+ *  Has special case for ISO dates and arrays which can be missing
+ *  month and day and still be valid.
+ *
+ *  @param $type
+ *    could be DATE_ARRAY, DATE_UNIX, DATE_DATETIME, DATE_ISO, or DATE_OBJECT
+ *  @param $granularity
+ *    The granularity of the date value provided. Set this for partial
+ *    dates so they pass validation.
+ */
+function _resource_conflict_date_is_valid($date, $type = DATE_DATETIME, $granularity = array('year', 'month', 'day', 'hour', 'minute')) {
+  if ($type == DATE_ISO && (!is_string($date) || !preg_match(DATE_REGEX_ISO, $date))) {
+    return FALSE;
+  }
+  if ($type == DATE_DATETIME && (!is_string($date) || !preg_match(DATE_REGEX_DATETIME, $date))) {
+    return FALSE;
+  }
+  return date_is_valid($date, $type, $granularity);
+}
+
+
