<?php
/**
 * @file
 * Allow uploading of files directly to YouTube via the browser using CORS.
 */

// Load all field hooks.
module_load_include('field.inc', 'media_youtube_upload');
// Load the YouTube api.
module_load_include('ytapi.inc', 'media_youtube_upload');
// Load all file callbacks.
module_load_include('file.inc', 'media_youtube_upload');
// Load the element callbacks.
module_load_include('element.inc', 'media_youtube_upload');
// Load the actions.
module_load_include('action.inc', 'media_youtube_upload');

// Define constants.
$native_youtube_fields = array(
  'field_file_youtube_title',
  'field_file_youtube_description',
  'field_file_youtube_privacy',
  'field_file_youtube_tags',
  'field_file_youtube_category',
  'field_file_youtube_thumb',
);
define('MEDIA_YOUTUBE_UPLOAD_NATIVE_YOUTUBE_FIELDS', serialize($native_youtube_fields));
define('MEDIA_YOUTUBE_UPLOADER_ALLOWED_EXTENSIONS', 'mov mpeg4 mp4 avi wmv mpegps flv 3gpp webm');
define('MEDIA_YOUTUBE_UPLOADER_MAX_UPLOADSIZE', '60 GB');

/**
 * Implements hook_help().
 */
function media_youtube_upload_help($path, $arg) {
  switch ($path) {
    case 'admin/config/media/media_youtube_upload':
      return '<p>' . t('The media youtube upload module provides a page, block and field to upload videos directly to YouTube. Use the settings below to configure your connection to the YouTube application. You can not use the upload widget without this configuration!') . '</p>';

    case 'admin/help#media_youtube_upload':
      $path = drupal_get_path('module', 'media_youtube_upload');
      $output = '';
      $output .= '<p>' . t('The media youtube upload module provides a page, block and field to upload videos directly to YouTube. When adding a field it is possible to choose which fields are available for the user to customize. And the default values that will show up or be used for the upload when not shown. When editing a YouTube video file it automatically pushes the changes to the YouTube video itself. This way you can implement a review process to only make a video public after review.') . '</p>';
      $output .= '<p>' . t('The media youtube upload module\'s requires the <a href="@settings">settings page</a> form to be filled out correctly to connect to the Google application. For you to be able to enter the settings you need to have both the "Google API php client" library and "Google CORS Upload" library installed as described in the <a href="@readme">README.txt</a>. If you enable the module through drush the libraries will get installed automatically.', array('@settings' => url('admin/config/media/media_youtube_upload'), '@readme' => url($path . '/README.txt'))) . '</p>';
      $output .= '<p>' . t('When you have all main settings configured you can decide where you want to use the YouTube upload. You have the option to use a page, block or field. Before you can use the upload widget of your choice, you have to respectively configure it\'s settings. Here are the options: <br /><ul><li><a href="@page_settings">Page settings</a> Used for the upload page at <a href="@upload_page">file/add/youtube</a> - <em>Optional redirection.</em></li><li><a href="@block_settings">Block settings</a> - <em>Optional redirection.</em></li><li><a href="@media_settings">Media settings</a> - <em>Used for file fields with the YouTube upload widget</em></li></ul> Field settings are captured when creating the field itself.', array(
        '@page_settings' => 'admin/config/media_youtube_upload/page_settings',
        '@block_settings' => 'admin/config/media_youtube_upload/block_settings',
        '@media_settings' => 'admin/config/media_youtube_upload/media_settings',
        '@upload_page' => 'file/add/youtube'
      ));
      return $output;
  }
}

/**
 * Implements hook_menu().
 */
function media_youtube_upload_menu() {
  $items = array();

  $items['admin/config/media/media_youtube_upload'] = array(
    'title' => 'Media youtube upload',
    'description' => 'Adjust YouTube account settings.',
    'file' => 'media_youtube_upload.admin.inc',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('media_youtube_upload_account_settings_form'),
    'access arguments' => array('administer media youtube upload'),
  );
  $items['admin/config/media/media_youtube_upload/page_settings'] = array(
    'title' => 'Page settings',
    'file' => 'media_youtube_upload.admin.inc',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('media_youtube_upload_upload_settings_form'),
    'access arguments' => array('administer media youtube upload'),
    'type' => MENU_LOCAL_TASK,
    'weight' => 0,
  );
  $items['admin/config/media/media_youtube_upload/block_settings'] = array(
    'title' => 'Block settings',
    'file' => 'media_youtube_upload.admin.inc',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('media_youtube_upload_upload_settings_form'),
    'access arguments' => array('administer media youtube upload'),
    'type' => MENU_LOCAL_TASK,
    'weight' => 1,
  );
  $items['admin/config/media/media_youtube_upload/media_settings'] = array(
    'title' => 'Media settings',
    'file' => 'media_youtube_upload.admin.inc',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('media_youtube_upload_upload_settings_form'),
    'access arguments' => array('administer media youtube upload'),
    'type' => MENU_LOCAL_TASK,
    'weight' => 2,
  );
  $items['media_youtube_upload/oauth2callback'] = array(
    'title' => 'YouTube callback',
    'page callback' => '_media_youtube_upload_ytcallback',
    'access arguments' => array('administer media youtube upload google application'),
    'type' => MENU_CALLBACK,
  );
  $items['file/add/youtube'] = array(
    'title' => 'Youtube upload',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('media_youtube_upload_upload_form', 'page_settings'),
    'access arguments' => array('upload media youtube upload files'),
    'type' => MENU_LOCAL_TASK,
  );
  $items['file/download/youtube/%/%/%'] = array(
    'title' => 'YouTube callback',
    'page callback' => '_media_youtube_upload_youtube_download_file',
    'page arguments' => array(3, 4, 5),
    'access callback' => TRUE,
    'type' => MENU_CALLBACK,
  );

  return $items;
}

/**
 * Implements hook_permission().
 */
function media_youtube_upload_permission() {
  $permissions = array();

  $permissions['administer media youtube upload'] = array(
    'title' => t('Administer Media: YouTube upload configuration.'),
  );
  $permissions['administer media youtube upload google application'] = array(
    'title' => t('Administer Media: YouTube uploads\' Google Application.'),
  );
  // TODO: Might have to split this up in seperate permissions per upload type.
  $permissions['upload media youtube upload files'] = array(
    'title' => t('Upload files with the Media: YouTube upload widget.'),
    'description' => t('Upload files directly to YouTube with the upload page, block, media widget or field widget.'),
  );

  return $permissions;
}

/**
 * Implements hook_media_browser_plugin_info().
 */
function media_youtube_upload_media_browser_plugin_info() {
  $info['media_youtube_upload'] = array(
    'title' => t('YouTube Upload'),
    'class' => 'MediaBrowserYoutubeUpload',
    'weight' => -10,
    'access callback' => 'user_access',
    'access arguments' => array('create files'),
  );

  return $info;
}

/**
 * Implements hook_cron_queue_info().
 */
function media_youtube_upload_cron_queue_info() {
  $queues['media_youtube_upload_set_thumbnail'] = array(
    'worker callback' => '_media_youtube_upload_set_thumbnail',
  );
  return $queues;
}

/**
 * Save YouTube's thumbnail image to our thumbnail field of the youtube file.
 *
 * @param object $youtube_file
 *   The YouTube file for which to set a thumbnail.
 *
 * @throws Exception
 *   Don't know if this should stay or go...
 *
 * @see media_youtube_upload_cron_queue_info()
 */
function _media_youtube_upload_set_thumbnail($youtube_file) {
  // If our file still exists go find the thumbnail. If not the item just gets
  // removed from the queue.
  if (file_load($youtube_file->fid)) {
    // Get the video id from file uri.
    $uri_parts = explode('/', $youtube_file->uri);
    $video_id = array_pop($uri_parts);

    // Get the (max sized) thumbnail image from YouTube.
    module_load_include('ytapi.inc', 'media_youtube_upload');
    $ytapi = new mediaYoutubeUploadYtapi();
    $imginfo = $ytapi->getTitleThumbs($video_id);

    $error = '';
    $field_language = field_language('file', $youtube_file, 'field_file_youtube_thumb');
    // Set an error text if we failed to get the thumbnail image.
    if (!empty($imginfo['error'])) {
      $error = $imginfo['error'];
    }
    // If the field of our thumb is empty, proceed.
    elseif (!isset($youtube_file->field_file_youtube_thumb[$field_language][0]['fid'])) {
      $video_title = $imginfo['title'];

      $remote_path = $imginfo['default_thumb'];
      $scheme     = file_default_scheme();
      $directory  = $scheme . '://youtube_thumbs';

      // Replace the existing one.
      if (file_prepare_directory($directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS)) {
        $result = drupal_http_request($remote_path);
        if (!empty($result->error) && $result->code != 404) {
          $error = t('Error @code getting the thumb: @error', array('@code' => $result->code, '@error' => $result->error));
        }

        // If the image is the default placeholder, reject it.
        elseif (md5($result->data) == 'e2ddfee11ae7edcae257da47f3a78a70') {
          $error = t('No thumbnail image generated yet by YouTube');
        }
        // Create the thumb.
        $code   = floor($result->code / 100) * 100;
        $types  = array('image/jpeg', 'image/png', 'image/gif');
        if (isset($result->data) && $result->data && $code != 500 && in_array($result->headers['content-type'], $types)) {
          $file = file_save_data($result->data, $directory . '/' . $video_id . '.jpg', FILE_EXISTS_REPLACE);
          $youtube_file->field_file_youtube_thumb[$field_language][0] = (array) $file;
          field_attach_update('file', $youtube_file);
        }
      }
    }
    if (!empty($error)) {
      watchdog('media_youtube_upload', 'Set thumbnail queue item with fid @fid failed! : !error', array(
        '@fid' => $youtube_file->fid,
        '@time' => date_iso8601($youtube_file->timestamp),
        '!error' => $error,
      ));
      throw new Exception('Error processing. Item will remain in the queue.');
    }
  }
}

/**
 * Implements hook_block_info().
 */
function media_youtube_upload_block_info() {
  $blocks = array();

  $blocks['media_youtube_upload_upload'] = array(
    'info' => t('YouTube upload element.'),
    'cache' => DRUPAL_NO_CACHE,
  );

  return $blocks;
}

/**
 * Implements hook_block_view().
 */
function media_youtube_upload_block_view($delta = '') {
  $block = array();

  switch ($delta) {
    case 'media_youtube_upload_upload':
      $block['subject'] = t('YouTube Upload');
      $form = drupal_get_form('media_youtube_upload_upload_form', 'block_settings');
      $block_content = drupal_render($form);

      $block['content'] = $block_content;
      break;
  }

  return $block;
}

/**
 * Form constructor for the upload form.
 *
 * @param string $settings_type
 *   Settings type for which to get the default values.
 *
 * @return array $form
 *   The constructed media_youtube_upload_upload element.
 *
 * @ingroup forms
 *
 * @see media_youtube_upload_menu()
 * @see media_youtube_upload_block_view()
 * @see MediaBrowserYoutubeUpload.inc
 */
function media_youtube_upload_upload_form($form = array(), &$form_state, $settings_type) {

  $token = variable_get('media_youtube_upload_token', array());
  if (empty($token)) {
    $form['notice'] = array(
      '#markup' => '<p>' . t('You need to have full authentication with YouTube to use the YouTube upload page. Please enter right crendentials on the <a href="@settings">settings page</a> and get a token.', array('@settings' => url('admin/config/media/media_youtube_upload'))) . '</p>',
    );
  }

  $form['youtube'] = array(
    '#type' => 'media_youtube_upload_upload',
    '#title' => t('Upload a new video'),
    '#required' => TRUE,
    '#default_value' => array('fid' => 0),
    '#upload_validators' => array(
      'allowed_extensions' => variable_get('media_youtube_upload_upload_' . $settings_type . '_allowed_extensions'),
      'max_uploadsize' => variable_get('media_youtube_upload_upload_' . $settings_type . '_max_uploadsize'),
    ),
    '#youtube_fields' => array(
      'enabled_fields' => variable_get('media_youtube_upload_upload_' . $settings_type . '_youtube_fields_enabled_fields'),
      'default_fid' => variable_get('media_youtube_upload_upload_' . $settings_type . '_fid'),
    ),
    '#settings_type' => $settings_type,
    '#weight' => 0,
  );

  if ($settings_type !== 'media_settings') {
    $form['youtube']['#youtube_redirect'] = variable_get('media_youtube_upload_upload_' . $settings_type . '_youtube_redirect', '');
  }

  return $form;
}

/**
 * Form constructor for the upload settings form.
 *
 * @ingroup forms
 *
 * @see media_youtube_upload_upload_settings_form_submit()
 */
function media_youtube_upload_upload_settings_form($form, &$form_state) {
  $parts = explode("/", request_uri());
  $settings_type = end($parts);
  $settings = array();
  // Get the current settings.
  $settings['youtube_fields']['enabled_fields'] = variable_get('media_youtube_upload_upload_' . $settings_type . '_youtube_fields_enabled_fields', array(
    'field_file_youtube_title' => 'field_file_youtube_title',
    'field_file_youtube_description' => 'field_file_youtube_description',
    'field_file_youtube_privacy' => '',
    'field_file_youtube_category' => '',
    'field_file_youtube_tags' => 'field_file_youtube_tags',
    'field_file_youtube_thumb' => '',
    )
  );
  $settings['upload_validators']['allowed_extensions'] = variable_get('media_youtube_upload_upload_' . $settings_type . '_allowed_extensions', MEDIA_YOUTUBE_UPLOADER_ALLOWED_EXTENSIONS);
  $settings['upload_validators']['max_uploadsize'] = variable_get('media_youtube_upload_upload_' . $settings_type . '_max_uploadsize', MEDIA_YOUTUBE_UPLOADER_MAX_UPLOADSIZE);
  $settings['fid'] = variable_get('media_youtube_upload_upload_' . $settings_type . '_fid', '');

  // Get the settings forms we need.
  $form['settings'] = array(
    '#type' => 'fieldset',
    '#title' => t('Upload'),
    '#description' => t('These %settings_type apply only to own widget respectively.', array(
      '%settings_type' => str_replace('_', ' ', $settings_type),
    )),
  );
  $form['settings']['widget_settings'] = _media_youtube_upload_get_field_widget_settings_form($settings);
  $form['settings']['youtube_fields'] = _media_youtube_upload_get_field_default_settings_form(NULL, $form_state, $settings['fid']);
  $form['settings']['instance_settings'] = _media_youtube_upload_get_field_instance_settings_form(NULL, $settings);

  if (in_array($settings_type, array('page_settings', 'block_settings'))) {
    $form['settings']['instance_settings']['youtube_redirect'] = array(
      '#type' => 'textfield',
      '#title' => t('Form redirection'),
      '#description' => t('After a video is successfully uploaded you can redirect to a certain url. This field accepts tokens.'),
      '#default_value' => variable_get('media_youtube_upload_upload_' . $settings_type . '_youtube_redirect', ''),
    );
    if (module_exists('token')) {
      $form['settings']['instance_settings']['token_tree'] = array(
        '#theme' => 'token_tree',
        '#token_types' => array('file'),
      );
    }
    else {
      $form['settings']['instance_settings']['youtube_redirect']['#description'] .= t('Enable the <a href="@drupal-token">Token module</a> to view the available token browser.', array('@drupal-token' => 'http://drupal.org/project/token'));
    }
  }
  $form['settings']['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save settings'),
  );

  return $form;
}

/**
 * Form validation handler.
 *
 * @ingroup forms
 *
 * @see media_youtube_upload_upload_settings_form()
 */
function media_youtube_upload_upload_settings_form_validate(&$form, &$form_state) {
  if (!form_get_errors()) {
    $file = $form['settings']['youtube_fields']['#default_file'];
    field_attach_form_validate('file', $file, $form, $form_state);
    field_attach_submit('file', $file, $form, $form_state);
    field_attach_presave('file', $file, $form, $form_state);
  }
}

/**
 * Form submission handler.
 *
 * @ingroup forms
 *
 * @see media_youtube_upload_upload_settings_form()
 */
function media_youtube_upload_upload_settings_form_submit($form, &$form_state) {
  $parts = explode("/", request_uri());
  $settings_type = end($parts);
  // Set our variables.
  variable_set('media_youtube_upload_upload_' . $settings_type . '_youtube_fields_enabled_fields', $form_state['values']['enabled_fields']);
  variable_set('media_youtube_upload_upload_' . $settings_type . '_allowed_extensions', $form_state['values']['allowed_extensions']);
  variable_set('media_youtube_upload_upload_' . $settings_type . '_max_uploadsize', $form_state['values']['max_uploadsize']);
  // Add redirect if it's not media settings.
  if ($settings_type !== 'media_settings') {
    variable_set('media_youtube_upload_upload_' . $settings_type . '_youtube_redirect', $form_state['values']['youtube_redirect']);
  }
  // Save a new file.
  if (empty($form_state['values']['fid']) || !file_load($form_state['values']['fid'])) {
    $file = file_save($form['settings']['youtube_fields']['#default_file']);
    variable_set('media_youtube_upload_upload_' . $settings_type . '_fid', $file->fid);
  }
  // Or update the config file.
  else {
    $file = file_load($form['settings']['youtube_fields']['#default_file']->fid);
    field_attach_form_validate('file', $file, $form, $form_state);
    field_attach_submit('file', $file, $form, $form_state);
    field_attach_presave('file', $file, $form, $form_state);
    file_entity_file_update($file);
  }
}

/**
 * Implements hook_ctools_plugin_api().
 */
function media_youtube_upload_ctools_plugin_api($module, $api) {
  if ($module == 'file_entity' && $api == 'file_type') {
    return array('version' => 1);
  }
  if ($module == 'file_entity' && $api == 'file_default_displays') {
    return array('version' => 1);
  }
}


/**
 * Implements hook_entity_view_alter().
 */
function media_youtube_upload_entity_view_alter(&$build, $entity_type) {
  // Check and see if we need to replace our page title.
  $replace_title = variable_get('media_youtube_upload_replace_page_title', FALSE);
  if ($entity_type == 'file' && $build['#bundle'] == 'youtube' && $build['#view_mode'] == 'full' && $replace_title) {
    // Get the YouTube video title and put it in a static variable.
    $file = file_load($build['#file']->fid);
    $items = field_get_items('file', $file, 'field_file_youtube_title');
    $item = reset($items);
    $title = field_view_value('file', $file, 'field_file_youtube_title', $item);

    $page_title = &drupal_static('media_youtube_upload_page_title');
    $page_title['title'] = $title['#markup'];
    $page_title['head_title'] = $title['#markup'];
  }
}

/**
 * Page title options for a full entity page view.
 *
 * @see media_youtube_upload_entity_view_alter()
 */
function media_youtube_upload_process_page(&$variables) {
  $page_title = drupal_static('media_youtube_upload_page_title');
  if (!empty($page_title)) {
    $variables['title'] = $page_title['title'];
    if (!empty($page_title['head_title'])) {
      drupal_set_title($page_title['head_title']);
    }
  }
}

/**
 * Google redirect here when user allowed application.
 *
 * @see media_youtube_upload_menu()
 */
function _media_youtube_upload_ytcallback() {

  $params = drupal_get_query_parameters();

  if (!empty($params['code'])) {
    module_load_include('ytapi.inc', 'media_youtube_upload');
    $ytapi = new MediaYoutubeUploadYtapi();
    $ytapi->getTokenFromCode($params['code']);
  }

  $token = variable_get('media_youtube_upload_token', array());
  if (!empty($token['refresh_token'])) {
    drupal_set_message(t('Token acquired from Google'), 'status', FALSE);
    drupal_set_message(t('Configuration successfully saved.'), 'status');
  }

  drupal_goto('admin/config/media/media_youtube_upload');

}

/**
 * Helper function to get country.
 *
 * @return string $country
 *   The ISO 3166-1 alpha-2 code for the selected country.
 */
function _media_youtube_upload_get_country() {
  $country = variable_get('media_youtube_upload_app_country', NULL);
  if (empty($country)) {
    $sd_country = variable_get('site_default_country', 'US');
    $country = empty($sd_country) ? 'US' : $sd_country;
  }
  return $country;
}

/**
 * Get cors_upload.js file.
 *
 * @return string|bool
 *   Return the path for the CORS upload library if found.
 */
function _media_youtube_upload_get_cors_upload() {
  $path = '';
  if (file_exists("sites/all/libraries/google-api-cors-upload/cors_upload.js")) {
    $path = "sites/all/libraries/google-api-cors-upload/cors_upload.js";
  }
  elseif (file_exists("sites/" . $_SERVER['SERVER_NAME'] . "/libraries/google-api-cors-upload/cors_upload.js")) {
    $path = "sites/" . $_SERVER['SERVER_NAME'] . "/libraries/google-api-cors-upload/cors_upload.js";
  }
  elseif (file_exists('profiles/' . drupal_get_profile() . '/libraries/google-api-cors-upload/cors_upload.js')) {
    $path = 'profiles/' . drupal_get_profile() . '/libraries/google-api-cors-upload/cors_upload.js';
  }
  else {
    return FALSE;
  }
  return $path;
}

/**
 * Helper function to add individual YouTube fields. Also alters the form_state.
 *
 * @param array $form
 *   The form structure where our fields are being attached to. This might be a
 *   full form structure, or a sub-element of a larger form.
 * @param array $form_state
 *   An associative array containing the current state of the form.
 * @param text $youtube_field
 *   The machine name of the YouTube field that needs to be attached.
 * @param object $file
 *   The file from which the fields are attached. This provides us with the
 *   default values.
 *
 * @return array
 *   Returns a form field element and also alters the form_state for defaults.
 */
function _media_youtube_upload_get_field_form($form = array(), &$form_state = array(), $youtube_field, $file) {
  $field = field_info_field($youtube_field['field_name']);
  $instance = field_info_instance($youtube_field['entity_type'], $youtube_field['field_name'], $youtube_field['bundle']);
  $items = field_get_items('file', $file, $youtube_field['field_name']);
  // Suggested solution not working:
  // http://drupal.stackexchange.com/questions/3875/form-element-default-value-and-ajax
  // unset($form_state['input'][$youtube_field['field_name']]);
  if ($field_form = field_default_form('file', $file, $field, $instance, LANGUAGE_NONE, $items, $form, $form_state)) {
    return $field_form;
  }
  return array();
}

/**
 * Implements hook_theme().
 */
function media_youtube_upload_theme() {
  return array(
    'media_youtube_upload_file_link' => array(
      'variables' => array(
        'file' => NULL,
        'icon_directory' => NULL
      ),
    ),
    'media_youtube_upload_file_icon' => array(
      'variables' => array(
        'file' => NULL,
        'icon_directory' => NULL
      ),
    ),
    'media_youtube_upload_managed_file' => array(
      'render element' => 'element',
    ),
    'media_youtube_upload_file_upload_help' => array(
      'variables' => array(
        'description' => NULL,
        'upload_validators' => NULL
      ),
    ),
    'media_youtube_upload_youtube_download_link' => array(
      'variables' => array(
        'video_id' => NULL,
        'filename' => 'download',
        'options' => array()
      ),
    ),
  );
}

/**
 * Returns HTML for a YouTube upload form element.
 *
 * @ingroup themeable
 */
function theme_media_youtube_upload_managed_file($variables) {
  $element = $variables['element'];
  $element['#attributes']['type'] = 'file';
  element_set_attributes($element, array('id', 'name', 'size', 'disabled'));
  _form_set_class($element, array('form-file'));
  // TODO: Change wrapper to a form #theme_wrapper attribute.
  $output = '';
  $output .= '<div class="media-youtube-uploader-form-managed-file form-managed-file">';
  $output .= '<input' . drupal_attributes($element['#attributes']) . ' />';
  $output .= '</div>';

  return $output;
}

/**
 * Returns HTML for help text based on YouTube upload validators.
 *
 * @ingroup themeable
 */
function theme_media_youtube_upload_file_upload_help($variables) {
  $description = $variables['description'];
  $settings = $variables['settings'];

  $descriptions = array();

  if (drupal_strlen($description)) {
    $descriptions[] = $description;
  }
  if (isset($settings['allowed_extensions'])) {
    $descriptions[] = t('Allowed file types: !extensions.', array('!extensions' => '<strong>' . check_plain($settings['allowed_extensions']) . '</strong>'));
  }
  if (isset($settings['max_uploadsize'])) {
    $descriptions[] = t('Files must be less than !size.', array('!size' => '<strong>' . format_size($settings['max_uploadsize']) . '</strong>'));
  }

  return implode('<br />', $descriptions);
}

/**
 * Returns HTML for a link to a YouTube video file.
 *
 * @ingroup themeable
 */
function theme_media_youtube_upload_file_link($variables) {

  $file = $variables['file'];
  $icon_directory = $variables['icon_directory'];

  $url = file_create_url($file->uri);
  $icon = theme('file_icon', array('file' => $file, 'icon_directory' => $icon_directory));

  // Set options as per anchor format described at
  // http://microformats.org/wiki/file-format-examples
  $options = array(
    'attributes' => array(
      'type' => $file->filemime . '; length=' . $file->filesize,
      'target' => '_blank',
    ),
  );

  // Use the description as the link text if available.
  if (empty($file->description)) {
    $link_text = $file->filename;
  }
  else {
    $link_text = $file->description;
    $options['attributes']['title'] = check_plain($file->filename);
  }

  return '<span class="file">' . $icon . ' ' . l($link_text, $url, $options) . '</span>';
}

/**
 * Returns HTML for a link to a YouTube video download link.
 *
 * @ingroup themeable
 */
function theme_media_youtube_upload_youtube_download_link($variables) {
  $video_id = $variables['video_id'];
  $filename = current(explode(".", $variables['filename']));
  $options = $variables['options'];
//  $video_id = 'owgPCYGxjfE';
  //$filename = 'test';

  // First get the video info page for this video id.
  // $my_video_info = 'http://www.youtube.com/get_video_info?&video_id='. $video_id;
  $my_video_info = 'http://www.youtube.com/get_video_info?&video_id=' . $video_id . '&asv=3&el=detailpage&hl=en_US';
  $my_video_info = _media_youtube_upload_curl_get($my_video_info);

  $thumbnail_url = $title = $url_encoded_fmt_stream_map = $type = $url = '';

  parse_str($my_video_info);
//  if($status=='fail'){
//    drupal_set_message(t('Error in video ID.'), 'error');
//  }

  if (isset($url_encoded_fmt_stream_map)) {
    /* Now get the url_encoded_fmt_stream_map, and explode on comma */
    $my_formats_array = explode(',', $url_encoded_fmt_stream_map);
  }
  else {
    drupal_set_message(t('No encoded format stream found.'), 'error');
  }
  if (count($my_formats_array) == 0 || empty($my_formats_array[0])) {
    //drupal_set_message(t('No format stream map found - was the video id correct?'), 'error');
    return t('No downloads found for this video');
  }
  else {
    // Create an array of available download formats.
    $avail_formats = array();
    $ipbits = $ip = $itag = $sig = $quality = '';
    $expire = time();
    foreach ($my_formats_array as $format) {
      parse_str($format);
      settype($itag, 'string');
      $avail_formats[$itag]['itag'] = $itag;
      $avail_formats[$itag]['quality'] = $quality;
      $type = explode(';', $type);
      $avail_formats[$itag]['type'] = $type[0];
      $extension_parts = explode('/', $avail_formats[$itag]['type']);
      $extension = end($extension_parts);
      $avail_formats[$itag]['url'] = urldecode($url) . '&signature=' . $sig;
      $filesize = _media_youtube_upload_curl_get_size($avail_formats[$itag]['url']);
      $avail_formats[$itag]['size'] = $filesize;
      parse_str(urldecode($url));
      $avail_formats[$itag]['expires'] = date("G:i:s T", $expire);
      $avail_formats[$itag]['ipbits'] = $ipbits;
      $avail_formats[$itag]['ip'] = $ip;
      // Construct the links if there is a video for it.
      if (_media_youtube_upload_curl_get_size($avail_formats[$itag]['url']) > 0) {
        // Direct link.
        $directlink = explode('.googlevideo.com/', $avail_formats[$itag]['url']);
        $directlink = 'http://redirector.googlevideo.com/' . $directlink[1] . '';
        $avail_formats[$itag]['direct'] = l(t('Download') . ' ' . $filename . '.' . $extension, $directlink, array('query' => array('title' => $filename))) . ' ' . '(' . _media_youtube_upload_format_bytes($filesize) . ')';
        // Proxy link.
        $avail_formats[$itag]['proxy'] = l(t('Download') . ' ' . $filename . '.' . $extension, '/file/download/youtube/' . urlencode($avail_formats[$itag]['type']) . '/' . urlencode($filename) . '/' . base64_encode($avail_formats[$itag]['url'])) . ' ' . '(' . _media_youtube_upload_format_bytes($filesize) . ')';
      }
    }
    // @see https://en.wikipedia.org/wiki/YouTube#Quality_and_formats
    $typemap = array();
    // MP4 High to Low.
    $typemap['85'] = array('weight' => 1, 'ext' => 'MP4', 'quality' => '1080p');
    $typemap['22'] = array('weight' => 2, 'ext' => 'MP4', 'quality' => '720p');
    $typemap['84'] = array('weight' => 3, 'ext' => 'MP4', 'quality' => '720p');
    $typemap['18'] = array('weight' => 4, 'ext' => 'MP4', 'quality' => '360p');
    $typemap['82'] = array('weight' => 5, 'ext' => 'MP4', 'quality' => '360p');
    $typemap['83'] = array('weight' => 6, 'ext' => 'MP4', 'quality' => '240p');
    // WebM High to Low.
    $typemap['43'] = array('weight' => 7, 'ext' => 'WEBM', 'quality' => '360p');
    $typemap['100'] = array('weight' => 8, 'ext' => 'WEBM', 'quality' => '360p');
    // FLV High to Low.
    $typemap['5'] = array('weight' => 9, 'ext' => 'FLV', 'quality' => '240p');
    // 3GP High to Low.
    $typemap['36'] = array('weight' => 10, 'ext' => '3GP', 'quality' => '240p');
    $typemap['17'] = array('weight' => 11, 'ext' => '3GP', 'quality' => '144p');

    $array = array_replace_recursive($avail_formats, $typemap);
    $array = array_intersect_key($array, $avail_formats);
    $weights = array();
    foreach ($array as $key => $val) {
      $weights[$key] = $val['weight'];
    }
    array_multisort($weights, SORT_ASC, $array);
    $links = array();
    foreach ($array as $key => $val) {
      if ($options['type'] == 'single_link' && $options['format'] == $val['type']) {
        return $val[$options['mode']];
      }
      elseif ($options['type'] == 'multiple_links') {
        $links[] = $val[$options['mode']];
      }
    }
    return theme_item_list(array('items' => $links, 'type' => 'ul', 'title' => NULL, 'attributes' => array()));
  }
}

/**
 * Function to get via cUrl.
 *
 * @author From lastRSS 0.9.1 by Vojtech Semecky, webmaster @ webdot . cz
 *
 * @see http://lastrss.webdot.cz/
 */
function _media_youtube_upload_curl_get($url) {
  $ch = curl_init();
  $timeout = 3;
  curl_setopt($ch, CURLOPT_URL, $url);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
  // If you want to force to ipv6, uncomment the following line.
  // curl_setopt( $ch , CURLOPT_IPRESOLVE , 'CURLOPT_IPRESOLVE_V6');
  $tmp = curl_exec($ch);
  curl_close($ch);
  return $tmp;
}

/**
 * Function to get filesize via cUrl.
 */
function _media_youtube_upload_curl_get_size($url) {
  $my_ch = curl_init();
  curl_setopt($my_ch, CURLOPT_URL, $url);
  curl_setopt($my_ch, CURLOPT_HEADER, TRUE);
  curl_setopt($my_ch, CURLOPT_NOBODY, TRUE);
  curl_setopt($my_ch, CURLOPT_RETURNTRANSFER, TRUE);
  curl_setopt($my_ch, CURLOPT_TIMEOUT, 10);
  $r = curl_exec($my_ch);
  foreach (explode("\n", $r) as $header) {
    if (strpos($header, 'Content-Length:') === 0) {
      return trim(substr($header, 16));
    }
  }
  return '';
}

/**
 * Function to download file mimicking headers.
 */
function  _media_youtube_upload_youtube_download_file($mime, $title, $token) {
  // Set operation params.
  $mime = urldecode($mime);
  $url = base64_decode($token);
  $extension  = str_replace(array('/', 'x-'), '', strstr($mime, '/'));
  $name = urldecode($title) . '.' . $extension;

  // Fetch and serve.
  if ($url) {
    $size = _media_youtube_upload_curl_get_size($url);
    // Generate the server headers.
    if (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== FALSE) {
      drupal_add_http_header('Content-Type', $mime);
      drupal_add_http_header('Content-Disposition', 'attachment; filename=' . $name . ';');
      drupal_add_http_header('Expires', '0');
      drupal_add_http_header('Content-Length', $size);
      drupal_add_http_header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0');
      drupal_add_http_header('Content-Transfer-Encoding', 'binary');
      drupal_add_http_header('Pragma', 'public');
    }
    else {
      drupal_add_http_header('Content-Type', $mime);
      drupal_add_http_header('Content-Disposition', 'attachment; filename=' . $name . ';');
      drupal_add_http_header('Content-Transfer-Encoding', 'binary');
      drupal_add_http_header('Expires', '0');
      drupal_add_http_header('Content-Length', $size);
      drupal_add_http_header('Pragma', 'no-cache');
    }

    readfile($url);
    drupal_exit();
  }
}

/**
 * Function to format bytes into a readable format.
 */
function _media_youtube_upload_format_bytes($bytes, $precision = 2) { 
  $units = array('B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
  $bytes = max($bytes, 0);
  $pow = floor(($bytes ? log($bytes) : 0) / log(1024));
  $pow = min($pow, count($units) - 1);
  $bytes /= pow(1024, $pow);
  return round($bytes, $precision) . '' . $units[$pow];
}
