<?php

/**
 * Implements hook_admin_paths().
 */
function entity_admin_admin_paths(){
  $paths = array();
  $entity_info = entity_admin_entity_get_info();
  foreach(array_keys($entity_info) as $entity_type){
    $class = $entity_info[$entity_type]['admin ui']['controller class'];
    if(@method_exists($class, 'ops')){
      $entity_path = entity_admin_entity_get_path($entity_type, $entity_info[$entity_type], '*');
      $entity_path = str_replace('%', '*', $entity_path);
      foreach(array_keys($class::ops()) as $op){
        $paths[$entity_path . '/' . $op] = TRUE;
      }
    }
  }
  return $paths;
}

/**
 * Implements hook_menu_local_tasks_alter().
 */
function entity_admin_menu_local_tasks_alter(&$data, $router_item, $root_path){
  // For all entity admin entities, change the local links into actions
  $entity_info = entity_admin_entity_get_info();
  foreach($entity_info as $info){
    if($info['fieldable']){
      if($root_path == $info['admin ui']['path']){
        if(isset($data['tabs'][1])){
          foreach(array_keys($data['tabs'][1]['output']) as $link_key){
            $item = $data['tabs'][1]['output'][$link_key];
            $item['#theme'] = 'menu_local_action';
            $data['actions']['output'][] = $item;
            unset($data['tabs'][1]['output'][$link_key]);
          }
        }
        return;
      }elseif($router_item['tab_parent'] == $info['admin ui']['path']){
        unset($data['tabs'][1]);
        return;
      }
    }
  }
}

/**
 * Implements hook_field_extra_fields().
 */
function entity_admin_field_extra_fields(){
  $extra = array();
  $entities_info = entity_admin_entity_get_info();
  foreach($entities_info as $entity_type => $entity_info){
    // Is there a label in the entity key
    if(is_array($entity_info['bundles']) && $label_key = entity_admin_entity_label_key($entity_info)){
      foreach(array_keys($entity_info['bundles']) as $bundle){
        $extra[$entity_type][$bundle] = array(
          'form' => array(
            'title' => array(
              'label' => t("Short title"),
              'description' => t('Entity module element'),
              'weight' => -5
            )
          )
        );
      }
    }
  }
  return $extra;
}

/**
 * Implementation of hook_entity_info_alter().
 */
function entity_admin_entity_info_alter(&$entity_info){
  foreach(array_keys(entity_admin_entity_get_info()) as $type){
    if($entity_info[$type]['fieldable']){
      $bundle_of_type = entity_admin_get_bundle_of_type($entity_info, $type);
      $path = $entity_info[$bundle_of_type]['admin ui']['path'];
      $bundle_argument = substr_count($path, '/') + 2;
      foreach(entity_admin_get_entities($bundle_of_type) as $name => $entity){
        $entity_info[$type]['bundles'][$name] = array(
          'label' => $entity->label,
          'admin' => array(
            'path' => $path . '/manage/%entity_admin_type',
            'real path' => $path . '/manage/' . $name,
            'bundle argument' => $bundle_argument,
            'access arguments' => array(
              'access content'
            )
          )
        );
      }
      if(!isset($entity_info[$type]['uri callback'])){
        $entity_info[$type]['uri callback'] = 'entity_admin_class_uri';
      }
    }elseif(isset($entity_info[$type]['bundle of'])){
      // We need to know what type of is used to build a prticular entity
      $entity_info[$entity_info[$type]['bundle of']]['type of'] = $type;
    }
    if(!isset($entity_info[$type]['form callback'])){
      $entity_info[$type]['form callback'] = 'entity_admin_metadata_form_entity';
    }
    if(!isset($entity_info[$type]['creation callback'])){
      $entity_info[$type]['creation callback'] = 'entity_admin_metadata_create_entity';
    }
  }
}

/*********************************************************************************************
 * 
 * Module functions
 * 
 ********************************************************************************************/
/**
 * 
 * Helper function to return the label key of an entity
 * @param array $entity_info
 */
function entity_admin_entity_label_key($entity_info){
  if(isset($entity_info['entity keys']['label'])){
    return $entity_info['entity keys']['label'];
  }else{
    return null;
  }
}

/**
 * Get the base path of an enity
 */
function entity_admin_entity_get_path($entity_type, $entity_info, $placeholder = null){
  $entityClass = isset($entity_info['entity class']) ? $entity_info['entity class'] : 'Entity';
  $bundle_key = $entity_info['bundle keys']['bundle'];
  $name_key = isset($entity_info['entity keys']['name']) ? $entity_info['entity keys']['name'] : $entity_info['entity keys']['id'];
  // Initiate an entity so we can get the path 
  $entity = new $entityClass(array(
    $bundle_key => false
  ), $entity_type);
  // So that the wildcards and *s (for admin paths) are put in the right part of the URL, set the ID of this dummy object to the placeholder 
  if($placeholder){
    $entity->{$name_key} = $placeholder;
  }
  $entity_uri = entity_uri($entity_type, $entity);
  return rtrim($entity_uri['path'], '/');
}

/**
 * 
 * Get a list of entity info items implementing entity ui
 */
function entity_admin_entity_get_info(){
  return array_filter(entity_get_info(), '_entity_admin_entity_info_filter');
}

/**
 * 
 * Array filter function - if variable $ui is set, use 
 * @param array $entity_info
 */
function _entity_admin_entity_info_filter($entity_info){
  if(isset($entity_info['admin ui']['controller class'])){
    if(property_exists($entity_info['admin ui']['controller class'], 'entityAdmin')){return true;}
  }
  return false;
}

function entity_admin_class_uri($entity){
  $entity_info = $entity->entityInfo();
  return array(
    'path' => str_replace('_', '-', $entity->entityType()) . '/' . $entity->identifier()
  );
}

/**
 * 
 * Check if the entity name exists
 * @param string $name
 * @param array $element
 * @param array $form_state
 */
function entity_admin_entity_name_exists($name, $element, $form_state){
  return entity_admin_get_entities($form_state['entity_type'], $name);
}

/**
 * Menu load function
 * Retrieve the entity type from the menu item & load it
 */
function entity_admin_type_load($bundle){
  list($url) = explode($bundle, $_GET['q']);
  $url .= $bundle;
  $menu_item = menu_get_item($url);
  $entity_type = array_shift($menu_item['page_arguments']);
  if($entities = entity_load_multiple_by_name($entity_type, array(
    $bundle
  ))){return $entities[$bundle];}
  return false;
}

/**
 * 
 * Get the bundle of type for an entity type
 */
function entity_admin_get_bundle_of_type($entity_info, $entity_type){
  foreach($entity_info as $type => $info){
    if(isset($info['bundle of']) && $info['bundle of'] == $entity_type){return $type;}
  }
  return null;
}

/**
 * Load multiple entities
 */
function entity_admin_load_multiple($entity_type, $ids = array(), $conditions = array(), $reset = FALSE){
  return entity_load($entity_type, $ids, $conditions, $reset);
}

/**
 * Load an entity of type (& optionally by name)
 */
function entity_admin_get_entities($type, $name = null){
  $types = entity_load_multiple_by_name($type, isset($name) ? array(
    $name
  ) : FALSE);
  return isset($name) ? reset($types) : $types;
}

/**
 * Helper function to create an entity
 */
function entity_admin_create($type, $values = array()){
  return entity_get_controller($type)->create($values);
}

/*********************************************************************************************
 * 
 * Menu callbacks & loaders
 * 
 ********************************************************************************************/
/**
 * Menu callback
 * Display an entity
 */
function entity_admin_page_view($entity, $view_mode = 'full'){
  $entity_type = $entity->entityType();
  $id = $entity->identifier();
  $controller = entity_get_controller($entity_type);
  $content = $controller->view(array(
    $id => $entity
  ));
  return $content;
}

/**
 * Menu title callback
 * Get an entity title
 */
function entity_admin_page_title($entity){
  return $entity->label();
}

/*********************************************************************************************
 * 
 * ENTITY TYPE FORMS
 * 
 ********************************************************************************************/
/**
 * Generic form for creating entity types
 */
function entity_admin_entity_type_form($form, &$form_state, $entity, $op = 'edit'){
  if($op == 'clone'){
    $entity->label .= ' (cloned)';
    $entity->type = '';
  }
  $form_state['entity_info'] = entity_get_info($form_state['entity_type']);
  $label_key = entity_admin_entity_label_key($form_state['entity_info']);
  $form[$label_key] = array(
    '#title' => t('Label'),
    '#type' => 'textfield',
    '#default_value' => isset($entity->label) ? $entity->label : '',
    '#description' => t('The human-readable name of this @label type.', array(
      '@label' => strtolower($form_state['entity_info'][$label_key])
    )),
    '#required' => TRUE,
    '#size' => 30
  );
  // Machine-readable type name.
  $form['type'] = array(
    '#type' => 'machine_name',
    '#default_value' => isset($entity->type) ? $entity->type : '',
    '#maxlength' => 32,
    '#machine_name' => array(
      'exists' => 'entity_admin_entity_name_exists',
      'source' => array(
        'label'
      )
    ),
    '#description' => t('A unique machine-readable name for this @label type. It must only contain lowercase letters, numbers, and underscores.', array(
      '@label' => strtolower($form_state['entity_info'][$label_key])
    ))
  );
  $form['actions'] = array(
    '#type' => 'actions'
  );
  $form['actions']['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save')
  );
  $form['actions']['cancel'] = array(
    '#markup' => l(t('Cancel'), $form_state['entity_info']['admin ui']['path'])
  );
  $form['#submit'] = array(
    'entity_admin_entity_type_form_submit'
  );
  unset($form['#validate']);
  return $form;
}

/**
 * Form API submit callback for the type form.
 */
function entity_admin_entity_type_form_submit(&$form, &$form_state){
  $entity = entity_ui_form_submit_build_entity($form, $form_state);
  // Save and go back.
  $entity->save();
  $form_state['redirect'] = $form_state['entity_info']['admin ui']['path'];
}

/*********************************************************************************************
 * 
 * ENTITY FORMS
 * 
 ********************************************************************************************/
function entity_admin_entity_form($form, &$form_state, $entity){
  $label_key = entity_admin_entity_label_key($entity->entityInfo());
  // Add the default field elements.
  $form[$label_key] = array(
    '#type' => 'textfield',
    '#title' => t('Label'),
    '#default_value' => isset($entity->{$label_key}) ? $entity->{$label_key} : '',
    '#maxlength' => 255,
    '#required' => TRUE,
    '#weight' => -5
  );
  $form_state['entity_type'] = $entity->entityType();
  $form_state['entity'] = $entity;
  // Add the field related form elements.
  $form_state[$entity->entityType()] = $entity;
  field_attach_form($entity->entityType(), $entity, $form, $form_state);
  $form['actions'] = array(
    '#type' => 'container',
    '#attributes' => array(
      'class' => array(
        'form-actions'
      )
    ),
    '#weight' => 400
  );
  $form['actions']['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save'),
    '#submit' => array(
      'entity_admin_entity_form_submit'
    )
  );
  return $form;
}

function entity_admin_entity_form_submit(&$form, &$form_state){
  global $user;
  $entity_type = $form_state[$form_state['entity_type']]->entityType();
  $entity = entity_ui_controller($entity_type)->entityFormSubmitBuildEntity($form, $form_state);
  if($entity->is_new = isset($entity->is_new) ? $entity->is_new : 0){
    $entity->created = time();
    $entity->uid = $user->uid;
  }
  $entity->changed = time();
  $form_state['id'] = $entity->save();
  $form_state['redirect'] = $entity->uri();
}

/**
 * Form callback: confirmation form for deleting an entity.
 *
 * @param $entity
 * The entity to delete
 *
 * @see confirm_form()
 */
function entity_admin_entity_delete_form($form, &$form_state, $entity){
  $form_state['entity'] = $entity;
  $entity_type = $entity->entityType();
  $form['#submit'][] = 'entity_admin_entity_delete_form_submit';
  $form = confirm_form($form, t('Are you sure you want to delete %title?', array(
    '%title' => entity_label($entity_type, $entity)
  )), $form_state['entity']->uri(), '<p>' . t('This action cannot be undone.') . '</p>', t('Delete'), t('Cancel'), 'confirm');
  return $form;
}

/**
 * Submit callback for publication_delete_form
 */
function entity_admin_entity_delete_form_submit($form, &$form_state){
  $entity = $form_state['entity'];
  $entity_type = $entity->entityType();
  $entity_info = $entity->entityInfo();
  entity_delete($entity->entityType(), entity_id($entity_type, $entity));
  drupal_set_message(t('The %label %title has been deleted.', array(
    '%label' => $entity_info['label'],
    '%title' => entity_label($entity_type, $entity)
  )));
  watchdog('Entity Admin', 'Deleted entity %title.', array(
    '%title' => entity_label($entity_type, $entity)
  ));
  $form_state['redirect'] = $entity_info['admin ui']['path'];
}

/*********************************************************************************************
 * 
 * ENTITY METADATA
 * 
 ********************************************************************************************/
/**
 * Callback to get the form of an entity.
 */
function entity_admin_metadata_form_entity($entity){
  // Pre-populate the form-state with the right form include.
  $form_state['build_info']['args'] = array(
    $entity
  );
  $form = drupal_build_form('entity_admin_entity_form', $form_state);
  return $form;
}

/**
 * Callback to get the form of an entity.
 */
function entity_admin_metadata_create_entity($values = array(), $entity_type){
  return entity_admin_create($entity_type, $values);
}

/*********************************************************************************************
 * 
 * VIEWS HOOKS
 * 
 ********************************************************************************************/
/**
 * Implementation of hook_views_api
 */
function entity_admin_views_api(){
  $path = drupal_get_path('module', 'entity_admin');
  return array(
    'api' => '3',
    'path' => $path . '/views'
  );
}

function entity_admin_entity_load_simple($entity_type, $ids = FALSE, $conditions = array()){
  $controller = new EntityAdminAPIController($entity_type);
  return $controller->load($ids, $conditions);
}

function entity_admin_preprocess_views_view(&$variables){
	
	if($variables['view']->tag == 'entity admin'){
		drupal_add_css(drupal_get_path('module', 'entity_admin') . '/css/entity-admin.css');
	}
	
	
}



