<?php
/**
 * @file
 * McHammer Mail composing tool.
 *
 */

/**
 * Implements hook_menu().
 */
function mchammer_menu() {

  $items = array();

  $items['admin/structure/mchammer'] = array(
    'title' => 'Mailing Composer',
    'access arguments' => array('administer mail templates'),
    'page callback' => 'system_admin_menu_block_page',
    'position' => 'left',
    'file' => 'system.admin.inc',
    'file path' => drupal_get_path('module', 'system'),
    'weight' => 1,
    'type' => MENU_NORMAL_ITEM,
  );

  $items['admin/structure/mchammer/settings'] = array(
    'title' => 'Mailing Composer settings',
    'description' => 'Configure general settings for Mailing Composer',
    'access arguments' => array('administer mail templates'),
    'page callback' => 'drupal_get_form',
    'page arguments' => array('mchammer_settings_form'),
    'file' => 'includes/admin.inc',
    'type' => MENU_NORMAL_ITEM,
  );

  $items['mail-template/%mchammer_mail_template_preview'] = array(
    'title' => 'Mail template',
    'access arguments' => array('preview mail templates'),
    'page callback' => 'mchammer_mail_template_page',
    'page arguments' => array(1),
    'file' => 'includes/pages.inc',
    'type' => MENU_CALLBACK,
  );

  $items['newsletter/%mchammer_newsletter_preview'] = array(
    'title' => 'Newsletter',
    'access arguments' => array('view all newsletters'),
    'page callback' => 'mchammer_newsletter_page',
    'page arguments' => array(1),
    'file' => 'includes/pages.inc',
    'type' => MENU_CALLBACK,
  );

  // Ajax driven callback to delete activity
  $items['mchammer/%ctools_js/rerender/%/%/%'] = array(
    'title' => 'Rerender mail template pane',
    'page callback' => 'mchammer_modal_rerender',
    'page arguments' => array(1, 3, 4, 5),
    'access arguments' => array('view all newsletters'),
    'file' => 'includes/pages.inc',
    'type' => MENU_CALLBACK,
  );

  return $items;

}

/**
 * Implements hook_theme().
 */
function mchammer_theme() {

  $theme = array(
    'page-mchammer' => array(
      'variables' => array(),
      'file' => 'includes/theme.inc',
      'function' => 'mchammer_page',
    ),
    'html-mchammer' => array(
      'variables' => array(),
      'template' => 'html-mchammer',
      'path' => drupal_get_path('module', 'mchammer') . '/templates',
    ),
    'panels_pane_mchammer' => array(
      'template' => 'panels-pane-mchammer',
      'path' => drupal_get_path('module', 'mchammer') . '/templates',
      'variables' => array('output' => array(), 'pane' => array(), 'display' => array()),
    ),
  );

  ctools_include('plugins', 'panels');
  $layouts = panels_get_layouts();
  foreach ($layouts as $name => $data) {
    if (isset($data['html-mchammer'])) {
      $theme['html-mchammer-' . $data['theme']] = array(
        'template' => $data['html-mchammer'],
        'path' => $data['path'],
        'variables' => array(),
      );
    }
  }

  return $theme;

}

/**
 * Implements hook_permission().
 */
function mchammer_permission() {
  return array(
    'administer mail templates' =>  array(
      'title' => t('Administer mail templates'),
      'description' => t('Add and edit mail templates.'),
    ),
    'preview mail templates' => array(
      'title' => t('Preview mail templates'),
      'description' => t('Preview mail templates')
    ),
    'view all newsletters' => array(
      'title' => t('View all newsletters'),
      'description' => t('View all newsletters')
    ),
    'create newsletters' => array(
      'title' => t('Create newsletters'),
      'description' => t('Create and derive newsletters')
    ),
  );
}

/**
 * Implements hook_ctools_plugin_directory().
 */
function mchammer_ctools_plugin_directory($module, $plugin) {
  if ($module == 'ctools' && in_array($plugin, array('export_ui', 'layouts', 'content_types'))) {
    return "plugins/$plugin";
  }
  elseif ($module == 'panels' && !empty($plugin)) {
    return "plugins/$plugin";
  }
}

/**
 * Implements hook_node_access().
 */
function mchammer_node_access($node, $op, $account) {

  // External preview mails (ex mailchimp) should also show non published nodes.
  if ($op == 'view' && _is_mchammer_page()) {
    return NODE_ACCESS_ALLOW;
  }

}

/**
 * Get the display cache for the mail_template or newsletter plugin.
 */
function _mchammer_panels_cache_get($key) {
  ctools_include('export-ui');

  if (preg_match("|template:|", $key)) {
    $plugin_name = 'mail_templates.export_ui';
    $machine_name = preg_replace("|template:|", "", $key);
  }
  else {
    $plugin_name = 'newsletter.export_ui';
    $machine_name = preg_replace("|newsletter:|", "", $key);
  }
  $plugin = ctools_get_export_ui($plugin_name);
  $handler = ctools_export_ui_get_handler($plugin);

  if (!$handler) {
    return;
  }

  $item = $handler->edit_cache_get($key);
  if (!$item) {
    $item = ctools_export_crud_load($handler->plugin['schema'], $machine_name);
  }

  return array($handler, $item, $machine_name);
}

/**
 * Get display edit cache for the MCHammer mail templates export UI
 *
 * The key is the second half of the key in this form:
 * mchammer:TASK_NAME:HANDLER_NAME;
 */
function mchammer_panels_cache_get($key) {

  ctools_include('common', 'panels');
  list($handler, $item, $machine_name) = _mchammer_panels_cache_get($key);

  if (!$item) {
    return FALSE;
  }

  if (isset($item->mchammer_display_cache)) {
    return $item->mchammer_display_cache;
  }

  $cache = new stdClass();
  $cache->display = $item->display;
  $cache->display->cache_key = 'mchammer:' . $key;
  $cache->content_types = panels_common_get_allowed_types('mchammer', $cache->display->context);
  $cache->display_title = TRUE;

  // @TODO support locking
  $cache->locked = FALSE;

  return $cache;
}

/**
 * Store a display edit in progress in the page cache.
 */
function mchammer_panels_cache_set($key, $cache) {
  list($handler, $item, $machine_name) = _mchammer_panels_cache_get($key);
  $item->mchammer_display_cache = $cache;
  $handler->edit_cache_set_key($item, $key);
}

/**
 * Save all changes made to a display using the MCHammer mail templates UI cache.
 */
function mchammer_panels_cache_clear($key, $cache) {
  list($handler, $item, $machine_name) = _mchammer_panels_cache_get($key);
  $handler->edit_cache_clear($item);
}

/**
 * Save all changes made to a display using the MCHammer mail templates UI cache.
 */
function mchammer_panels_cache_save($key, $cache) {
  list($handler, $item, $machine_name) = _mchammer_panels_cache_get($key);
  $item->display = $cache->display;
  mchammer_mail_template_save($item);
  $handler->edit_cache_clear($item);
}

/**
 * Implements hook_form_{ctools_node_content_type_edit_form}_alter().
 */
function mchammer_form_ctools_node_content_type_edit_form_alter(&$form, $form_state) {

  if (arg(2) != 'mchammer_newsletter' && arg(2) != 'mchammer') {
    return;
  }

  // Only show searchbox + view modes.
  $form['override_title']['#access'] = FALSE;
  $form['override_title_text']['#access'] = FALSE;
  $form['leave_node_title']['#access'] = FALSE;
  $form['link_node_title']['#access'] = FALSE;
  $form['identifier']['#access'] = FALSE;
  $form['links']['#access'] = FALSE;
  unset($form['override_title_markup']);

  // Default options
  $form['leave_node_title']['#default_value'] = TRUE;
  $form['override_title']['#default_value'] = TRUE;

  // Get the Template from the newsletter.
  if (isset($form['build_mode']) && preg_match("|mchammer:newsletter:|", $form_state['display']->cache_key)) {

    // Limit the view modes to the template setting.
    if (arg(3) == 'edit-pane') {
      $region = $form_state['pane']->panel;
    }
    else {
      $region = arg(5);//$form_state['display']->content[$pane->pid]->panel
    }

    $enabled_view_modes = array_filter($form_state['display']->panel_settings['view_modes_settings'][$region]['view_modes']);
    if (!$enabled_view_modes) {
      $enabled_view_modes = array_filter(variable_get('mchammer_view_modes', array()));
    }

    $options = array();
    foreach ($form['build_mode']['#options'] as $option => $title) {
      if (isset($enabled_view_modes[$option])) {
        $options[$option] = $title;
      }
    }
    $form['build_mode']['#options'] = $options;

  }

}

/**
 * Implements hook_preprocess_page().
 * Set the theme hook to page-mchammer for newsletter pages.
 */
function mchammer_preprocess_page(&$variables) {

  if (_is_mchammer_page()) {
    $object = (arg(0) == 'newsletter') ? mchammer_newsletter_preview_load(arg(1)) : mchammer_mail_template_preview_load(arg(1));
    if ($object) {
      $variables['theme_hook_suggestion'] = 'page-mchammer';
      include_once(dirname(__FILE__) . '/includes/theme.inc');
    }
  }

}

/**
 * Implements hook_process_html().
 * Set the theme hook suggestion to html-mchammer for newsletter pages.
 * Reset all css / js.
 */
function mchammer_process_html(&$variables) {

  if (_is_mchammer_page()) {

    $variables['scripts'] = '';
    $variables['styles'] = '';

    $object = (arg(0) == 'newsletter') ? mchammer_newsletter_preview_load(arg(1)) : mchammer_mail_template_preview_load(arg(1));
    if ($object) {

      ctools_include('plugins', 'panels');
      $layout = panels_get_layout($object->display->layout);

      // Add template variables from layout
      if (isset($object->display->panel_settings['variables'])) {
        $variables += $object->display->panel_settings['variables'];
      }

      if (isset($layout['html-mchammer'])) {
        array_unshift($variables['theme_hook_suggestions'], 'html-mchammer-' . $layout['theme']);
      }

      array_unshift($variables['theme_hook_suggestions'], 'html-mchammer');

    }

  }

}

/**
 * Implements hook_preprocess_panels_pane().
 * Use the mc hammer pane template.
 */
function mchammer_preprocess_panels_pane(&$vars) {
  if (_is_mchammer_page()) {
    $vars['theme_hook_suggestions'] = array('panels_pane_mchammer');
  }
}

/**
 * Preprocess the primary entry level theme.
 */
function mchammer_preprocess_panels_add_content_modal(&$vars) {

  // Make sure categories_array() exists.
  if (!isset($vars['categories_array'])) {
    $vars['categories_array'] = array();
  }

}

/**
* Implements hook_url_outbound_alter().
*/
function mchammer_url_outbound_alter(&$path, &$options, $original_path) {

  if (arg(0) == 'newsletter') {
    $options['absolute'] = TRUE;
  }

}

/**
 * Determines whether the given user has access to a mail.
 */
function mchammer_mail_template_access() {
  return user_access('administer mail templates');
}

/**
 * List callback to show templates through CTools.
 */
function mchammer_mail_templates_list() {

  $names = array();
  ctools_include('export');
  foreach(ctools_export_crud_load_all('mchammer_mail_templates') as $template) {
    $names[$template->name] = $template->admin_title;
  }

  return $names;

}

/**
 * Load a mchammer mail template.
 */
function mchammer_mail_template_load($name) {
  return mchammer_ctools_crud_load($name, 'mchammer_mail_templates');
}

/**
 * Write a McHammer mail template to the database.
 */
function mchammer_mail_template_save(&$mail_template) {
  return mchammer_ctools_crud_save($mail_template, 'mchammer_mail_templates', 'mtid');
}

/**
 * Load a mchammer newsletter.
 */
function mchammer_newsletter_load($name) {
  return mchammer_ctools_crud_load($name, 'mchammer_newsletters');
}

/**
 * Write a McHammer newsletter to the database.
 */
function mchammer_newsletter_save(&$mail_template) {
  return mchammer_ctools_crud_save($mail_template, 'mchammer_newsletters', 'mnid');
}

/**
 * Load a preview mail template.
 */
function mchammer_mail_template_preview_load($id) {

  // If the id is 'new'. Get it from cache
  if ($id == 'new') {
    $template = panels_edit_cache_get('mchammer:template:::add');
  }
  else {
    $template = mchammer_mail_template_load($id);
  }

  if (!isset($template->display->renderer)) {
    return FALSE;
  }

  return $template;

}

/**
 * Load a mchammer newsletter.
 */
function mchammer_newsletter_preview_load($id) {

  // If the id is 'new'. Get it from cache
  if ($id == 'new') {
    $newsletter = panels_edit_cache_get('mchammer:newsletter:::add');
  }
  else {
    $newsletter = mchammer_newsletter_load($id);
  }

  if (!isset($newsletter->display->renderer)) {
    return FALSE;
  }

  return $newsletter;

}

/**
 * Helper function to load a cached display of CTools export objects
 * inside McHammer.
 */
function mchammer_ctools_crud_load($name, $table) {

  $cache = &drupal_static($table, array());

  // We use array_key_exists because failed loads will be NULL and
  // isset() will try to load it again.
  if (!array_key_exists($name, $cache)) {
    ctools_include('export');
    $result = ctools_export_load_object($table, 'names', array($name));
    if (isset($result[$name])) {
      if (!empty($result[$name]->did)) {
        $result[$name]->display = panels_load_display($result[$name]->did);
        if (!empty($result[$name]->title) && empty($result[$name]->display->title)) {
          $result[$name]->display->title = $result[$name]->title;
        }
      }
      $cache[$name] = $result[$name];
      if (!empty($result[$name]->title)) {
        $cache[$name]->title = $result[$name]->title;
      }
    }
    else {
      $cache[$name] = NULL;
    }
  }

  if (isset($cache[$name])) {
    return $cache[$name];
  }

}

/**
 * Helper function to save a cached display of CTools export objects
 * inside McHammer.
 */
function mchammer_ctools_crud_save(&$object, $table, $id) {

  $schema = ctools_export_get_schema($table);
  $export = $schema['export'];
  
  // Objects should have a serial primary key. If not, simply fail to write.
  if (empty($export['primary key'])) {
    return FALSE;
  }
  
  $key = $export['primary key'];

  if (!empty($object->display)) {
    $display = panels_save_display($object->display);
    $object->did = $display->did;
  }
  
  // Existing record.
  if ($object->export_type & EXPORT_IN_DATABASE) {
  // if (isset($object->$id) && $object->$id != 'new')
    $update = array($key);
  }
  // New record (includes cloned records).
  else {
    $update = array();
    $object->export_type = EXPORT_IN_DATABASE;
    $object->$id = NULL;
    
    if (!empty($object->originalName) && $object->formType == 'clone') {
      $cloned_display = mchammer_clone_display($object, $table);
      $display = panels_save_display($cloned_display);
      $object->did = $display->did;
    }
    
  }
  
  drupal_write_record($table, $object, $update);

  // add update and insert hooks
  if ($update) {
    $hook = ($table == 'mchammer_newsletters') ? 'mchammer_newsletter_update' : 'mchammer_mail_template_update';
  }
  else {
    $hook = ($table == 'mchammer_newsletters') ? 'mchammer_newsletter_insert' : 'mchammer_mail_template_insert';
  }

  module_invoke_all($hook, $object);

  return $object;

}

/**
 * Copy the display and panes from one display to another
 * .
 * @param $object 
 *   A MCHammer newsletter UI component.
 *   
 * @param $table
 *   The CTools export table.
 * @return A new generated panel display.
 */
function mchammer_clone_display($object, $table) {

  ctools_include('content');

  if ($table == 'mchammer_newsletters') {
    $source = mchammer_newsletter_load($object->originalName);
  }
  else {
    // Load the original mail template
    $source = mchammer_mail_template_load($object->originalName);
  }
  if (!$source) {
    return;
  }

  $display = panels_new_display();

  // Inherit the layout.
  $display->layout = $source->display->layout;

  // Inherit the panel_settings.
  $display->panel_settings = $source->display->panel_settings;

  // Add the Master template name to the derived Newsletter.
  $display->panel_settings['template_name'] = $source->name;

  // Construct the panes for the new display
  foreach ($source->display->panels as $region) {

    foreach ($region as $pid) {

      $pane = $source->display->content[$pid];

      $extractor = McHammerExtractorFactory::getExtractor($pane->type, $source->display);
      $extractor->extract($display);

    }

  }

  return $display;

}

/**
 * Render the system main block only.
 * @param $element Render array
 */
function mchammer_render_page_content($element) {

  $output = '';
  foreach (element_children($element) as $key) {

    if ($key == 'system_main') {
      return drupal_render($element[$key]);
    }
    else {
      $output = mchammer_render_page_content($element[$key]);
    }

    if (!empty($output)) {
      return $output;
    }

  }

  return $output;

}

/**
 * Theme utility function to print content regions.
 */
function mchammer_print($content, $target_region) {
  foreach ($content as $key => $text) {
    list($region, $source_name) = explode("::", $key);
    if ($region == $target_region) {
      print $text;
    }
  }
}

/**
 * Helper function to check if current page belongs to mc hammer.
 */
function _is_mchammer_page() {
  return (arg(0) == 'newsletter' || arg(0) == 'mail-template');
}