<?php

/**
 * Implements hook_menu().
 */
function form_builder_field_menu() {
  $items = array();
  $items['form-builder-field/%'] = array(
    'type' => MENU_CALLBACK,
    'page callback' => 'form_builder_field_modal',
    'page arguments' => array(1, 2),
    'access arguments' => array('access content'), // @TODO:  make this better
  );

  return $items;
}

function form_builder_field_modal($form_id) {
  $html = render(form_builder_crud_interface($form_id));

  $json = array(
    'status' => TRUE,
    'data' => $html,
  );

  drupal_json_output($json);
}

/**
 * Implements hook_field_info().
 */
function form_builder_field_field_info() {
  return array(
    'form_builder' => array(
      'label' => t('Form Builder'),
      'description' => t('This field stores a form in the database.'),
      'settings' => array(),
      'instance_settings' => array(),
      'default_widget' => 'form_builder',
      'default_formatter' => 'form_builder',
    ),
  );
}

/**
 * Implements hook_field_widget_info().
 */
function form_builder_field_field_widget_info() {
  return array(
    'form_builder' => array(
      'label' => t('Form Builder'),
      'field types' => array('form_builder'),
      'settings' => array(),
      'behaviors' => array(
        'multiple values' => FIELD_BEHAVIOR_CUSTOM,
        'default value' => FIELD_BEHAVIOR_DEFAULT,
      ),
    ),
  );
}

function form_builder_field_form_field_ui_field_edit_form_alter(&$form, &$form_state) {
  if ($form['#field']['type'] == 'form_builder') {
    // Hide the cardinality setting on the field settings for form_builder fields.
    $form['field']['cardinality']['#default_value'] = 1;
    $form['field']['#access'] = FALSE;
  }
}

/**
 * Implements hook_field_formatter_info().
 */
function form_builder_field_field_formatter_info() {
 return array(
   'form_builder' => array(
     'label' => t('Default'),
     'field types' => array('form_builder'),
   ),
 );
}

/**
 * Build a new id for a form_id
 *
 * @param $id string
 * @param $reset bool
 *
 * @return string
 */
function form_builder_field_new_id($id, $reset = FALSE) {
  $form_ids = &$_SESSION['fbf_email_ids'];

  if ($reset) {
    unset($form_ids[$id]);
  }

  if (!isset($form_ids[$id])) {
    $form_ids[$id] = $id + rand();
    // prime the form builder cache

  }

  return $form_ids[$id];
}

/**
 * Implements hook_field_widget_form().
 */
function form_builder_field_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
  global $base_url;
  static $form_loaded = FALSE;

  if (isset($items[$delta]['form_id'])) {
    $form_id = $items[$delta]['form_id'];
  }
  else {
    // Is this an entity already?
    list($id, $vid, $bundle) = entity_extract_ids($instance['entity_type'], $element['#entity']);

    if (empty($id) || empty($vid)) {
      $form_id = form_builder_field_new_id($instance['id'], TRUE);
    }
    else {
      // This occurs if something bad happened during the initial insert.  it should be rare.
      $form_id = form_builder_field_build_id($instance['id'], $form['#entity'], $instance['entity_type']);
    }

  }

  drupal_add_library('system', 'ui.dialog');
  $form['#attached']['js'][] = drupal_get_path('module', 'form_builder_field') . '/form_builder_field.js';
  // Add a js var for the getJSON url.
  // This helps with subdomains, preventing 404's.
  drupal_add_js(array('form_builder_field' => array('base_url' => $base_url)), 'setting');

  $element['form_id'] = array(
    '#type' => 'hidden',
    '#value' => $form_id,
  );

  $options = array(
    'attributes' => array(
      'class' => array('form-builder-field-open-form'),
      'data-formid' => $form_id,
    ),
    'fragment' => 'form-builder-field-form'
  );

  $element['click_me'] = array(
    '#markup' => l(t('Edit Form'), '', $options),
    '#suffix' => '<div class="form-builder-field-progress ajax-progress"></div>',
  );

  // Go ahead and load a form so all the css/js can be loaded correctly.
  // Sometimes the prefix is not set to appending would throw warning.
  $prefix = (isset($form['#prefix']) ? $form['#prefix'] : '');
  if (!$form_loaded) {
    $form_loaded = TRUE;
    $prefix .= '<div class="form-builder-field-form">' .
      drupal_render(form_builder_crud_interface($form_id)) . '</div>';
    $form['#prefix'] = $prefix;
  }

  if (isset($form_state['input']) && !empty($form_state['input'])) {
    $element['form_id']['#value'] = $form_state['input'][$field['field_name']][$langcode]['form_id'];
  }

  return $element;
}

/**
 * Implements hook_field_insert()
 */
function form_builder_field_field_insert($entity_type, $entity, $field, $instance, $langcode, &$items) {
  module_load_include('inc', 'form_builder', 'includes/form_builder.api');
  module_load_include('inc', 'form_builder', 'includes/form_builder.cache');
  if (!form_builder_crud_load($items[0])) {
    $form_id = form_builder_field_build_id($instance['id'], $entity, $entity_type);
    form_builder_field_move_forms_cache($items[0], $form_id);
    form_builder_field_new_id($instance['id'], TRUE);
    $items = array(array('form_id' => $form_id));
  }
  form_builder_crud_save_form($items[0]['form_id']);
}

/**
 * Implements hook_field_update()
 */
function form_builder_field_field_update($entity_type, $entity, $field, $instance, $langcode, &$items) {
  module_load_include('inc', 'form_builder', 'includes/form_builder.api');
  module_load_include('inc', 'form_builder', 'includes/form_builder.cache');
  if(is_array($items[0])) {
      $form_id = $items[0]['form_id'];
  }
  else {
    $form_id = $items[0];
  }
  if (module_exists('state_machine') && $form_id == 'n') {
   $form_id =  $instance['id'] . '-' . $entity_type . '-' . $entity->nid . '-' . $entity->original->vid;
  }

  $new_form_id = form_builder_field_build_id($instance['id'], $entity, $entity_type);

  if (!form_builder_crud_load($new_form_id)) {
    form_builder_field_move_forms_cache($form_id, $new_form_id);
    form_builder_field_new_id($instance['id'], TRUE);
    form_builder_crud_save_form($new_form_id);
    $items[0] = array('form_id' => $new_form_id);
  }
  else {
    $form = form_builder_crud_load($form_id);
    $form_cache = unserialize($form['form']);
    form_builder_crud_save_form($form_id);
    form_builder_cache_save('crud', $form_id, $form_cache);
    $items[0] = array('form_id' => $form_id);
  }
}

/**
 * Implements hook_field_is_empty().
 */
function form_builder_field_field_is_empty($item, $field) {
  return !empty($item['to_address']['to_address']);
}


function form_builder_field_move_forms_cache($old_form_id, $new_form_id) {
  module_load_include('inc', 'form_builder', 'includes/form_builder.api');
  module_load_include('inc', 'form_builder', 'includes/form_builder.cache');

  $form_cache = form_builder_cache_load('crud', $old_form_id, NULL, TRUE);
  form_builder_cache_load(NULL, NULL, NULL, TRUE);
  if (!$form_cache) {
    $form = form_builder_crud_load($old_form_id);
    $form_cache = unserialize($form['form']);
  }
  form_builder_cache_save('crud', $new_form_id, $form_cache);
  form_builder_cache_delete('crud', $old_form_id);
}

/**
 * @param $instance_id
 * @param $entity
 *  This could the the entity or an array with array('id' => id, 'vid' => vid)
 * @param $type
 *
 * @return string
 */
function form_builder_field_build_id($instance_id, $entity, $type) {
  // if $entity is an array then we were passed array('id', 'vid')
  if (is_array($entity)) {
    $rev_id = empty($entity['vid']) ? 0 : $entity['vid'];
    $id = $entity['id'];
  }
  else {
    $entity_info = entity_get_info($type);
    $id = $entity->{$entity_info['entity keys']['id']};
    if (empty($entity_info['entity keys']['revision'])) {
      $rev_id = 0;
    }
    else {
      $rev_id = $entity->{$entity_info['entity keys']['revision']};
    }
  }


  return "$instance_id-$type-$id-$rev_id";
}

/**
 * Implements hook_forms()
 * Since a node can have multiple form_builder_field fields we need this
 */
function form_builder_field_forms($form_id, $args) {
  $forms = array();
  if (strstr($form_id, 'fbf_form_') !== FALSE) {
    $forms[$form_id] = array(
      'callback' => 'form_builder_field_form',
    );
  }
  return $forms;
}

/**
 * The form builder form
 */
function form_builder_field_form($form, &$form_state, $form_builder_id, $entity_type, $entity, $field, $instance, $langcode, $display) {

  $form['#base'] = 'form_builder_field_form_submit';

  $form = array(
    'form' => form_builder_crud_form_load($form_builder_id),
    '#tree' => TRUE
  );

  $form['entity'] = array(
    '#type' => 'value',
    '#value' => $entity,
  );

  $form['entity_type'] = array(
    '#type' => 'value',
    '#value' => $entity_type,
  );

  $form['field'] = array(
    '#type' => 'value',
    '#value' => $field,
  );

  $form['instance'] = array(
    '#type' => 'value',
    '#value' => $instance,
  );

  $form['langcode'] = array(
    '#type' => 'value',
    '#value' => $langcode,
  );

  $form['display'] = array(
    '#type' => 'value',
    '#value' => $display,
  );

  $form['form_builder_id'] = array(
    '#type' => 'value',
    '#value' => $form_builder_id,
  );

  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => 'Save',
  );

  return $form;
}

/**
 * Validate the form
 */
function form_builder_field_form_validate(&$form, &$form_state) {
  foreach(module_implements('form_builder_field_validate') as $module) {
    $function = "{$module}_form_builder_field_validate";
    $function($form, $form_state);
  }
}

/**
 * Submit function for the form
 */
function form_builder_field_form_submit(&$form, &$form_state) {
  $values = array(
    'form_id' => $form_state['values']['form_builder_id'],
    'entity' => $form_state['values']['entity'],
  ) + $form_state['values']['form'];

  form_builder_field_run_actions($values, $form, $form_state);
}

/**
 * Implements hook_field_formatter_view()
 */
function form_builder_field_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
  if (isset($items[0]['form_id'])) {
    $form_id = $items[0]['form_id'];
  }
  else {
    $form_id = form_builder_field_build_id($instance['id'], $entity, $entity_type);
  }
  $form = drupal_get_form('fbf_form_' . $form_id, $form_id, $entity_type, $entity, $field, $instance, $langcode, $display);

  return $form;
}

/**
 * Run actions after the node has been saved.
 */
function form_builder_field_run_actions($values, &$form, &$form_state) {
  foreach(module_implements('form_builder_field_action') as $module) {
    $function = "{$module}_form_builder_field_action";
    $function($values, $form, $form_state);
  }
}


/**
 * Load the current form_builder from for the active session
 *
 * @param $instance array
 *  The field instance from @see field_info_instance
 * @param $entity
 *  The entity
 *
 * @return array
 *  The form array
 */
function form_builder_field_load_field_info($instance, $entity) {
  $form_id = form_builder_field_build_id($instance['id'], $entity, $instance['entity_type']);

  if ($form = form_builder_crud_form_load($form_id)) {
    return $form;
  }

  // We don't have an actually entity yet
  $form_id = form_builder_field_new_id($instance['id']);

  return form_builder_crud_form_load($form_id);
}