<?php
/**
 * WPZOOM_Video_Thumb Class
 *
 * @package WPZOOM
 * @subpackage Video_Thumb
 */


class WPZOOM_Video_Thumb extends WPZOOM_Video_API {
    public static $youtube_thumbnail_sizes = array( 'maxresdefault', 'hqdefault', 'mqdefault', 'default', 'sddefault' );

    public static function init() {
        if(current_user_can('edit_posts')) {
            add_action('wp_ajax_wpzoom_autothumb_get', array(__CLASS__, 'admin_ajax_thumb_get'));
            if(current_user_can('upload_files')) add_action('wp_ajax_wpzoom_autothumb_attach', array(__CLASS__, 'admin_ajax_thumb_attach'));
            add_action('admin_head-post-new.php', array(__CLASS__, 'admin_newpost_head'), 100);
            add_action('admin_head-post.php', array(__CLASS__, 'admin_newpost_head'), 100);
            add_action('admin_footer-post-new.php', array(__CLASS__, 'admin_newpost_foot'), 100);
            add_action('admin_footer-post.php', array(__CLASS__, 'admin_newpost_foot'), 100);
        }
    }

    /**
     * Called when we receive the AJAX call to fetch a thumbnail from a given URL
     */
    public static function admin_ajax_thumb_get() {
        if (isset($_POST['wpzoom_autothumb_embedcode']) && isset($_POST['wpzoom_autothumb_postid'])) {
            $url = parent::extract_url_from_embed(trim(stripslashes($_POST['wpzoom_autothumb_embedcode'])));
            $postid = intval($_POST['wpzoom_autothumb_postid']);

            if(empty($url) || filter_var($url, FILTER_VALIDATE_URL) === false || $postid < 1) die('ERROR');

            $thumb_url = self::fetch_video_thumbnail($url, $postid);
            header('Content-type: application/json');
            die($thumb_url !== false ? json_encode($thumb_url) : 'ERROR');
        }
    }

    /**
     * Called when we receive the AJAX call to attach a given thumbnail URL to a given post
     */
    public static function admin_ajax_thumb_attach() {
        if(isset($_POST['wpzoom_autothumb_embedcode']) && isset($_POST['wpzoom_autothumb_postid']) && isset($_POST['wpzoom_autothumb_nonce'])) {
            $url = parent::extract_url_from_embed(trim(stripslashes($_POST['wpzoom_autothumb_embedcode'])));
            $postid = intval($_POST['wpzoom_autothumb_postid']);
            $nonce = trim($_POST['wpzoom_autothumb_nonce']);

            if(empty($url) || filter_var($url, FILTER_VALIDATE_URL) === false || $postid < 1 || !wp_verify_nonce($nonce, 'wpzoom_attach_thumbnail-' . $postid)) return false;

            header('Content-type: text/plain');
            $id = self::attach_remote_video_thumb($url, $postid);
            die($id !== false && $id > 0 ? '' . $id : 'false');
        }
    }

    /**
     * Just some styles to make things look better
     */
    public static function admin_newpost_head() {
        ?><style type="text/css">
            #layout_select1 { position: relative; }
            #wpz_autothumb { position: relative; }
            #wpzoom_autothumb_preview { display: none; text-align: center; margin: 0; }
            #normal-sortables #wpzoom_autothumb_preview { display: none; text-align: left; margin: 0; }
            #wpzoom_autothumb_preview img { display: block; width: 100%; margin-bottom: 5px; }
            #normal-sortables #wpzoom_autothumb_preview img { display: block; width: 300px; margin-bottom: 5px; }
            #normal-sortables .wpzoom_video_external_preview img { display: block; width: 300px; margin-bottom: 5px; }
            #wpzoom_autothumb_preview #wpz_usethis { display: inline-block; text-align: center; line-height: 15px; padding: 3px 10px; cursor: pointer; }
            #normal-sortables #wpzoom_autothumb_preview #wpz_usethis { display: inline-block; text-align: left; line-height: 15px; padding: 3px 10px; cursor: pointer; }
            #normal-sortables .wpzoom_video_external_preview #wpz_usethis { display: inline-block; text-align: left; line-height: 15px; padding: 3px 10px; cursor: pointer; }
            #wpzoom_autothumb_preview #wpz_usethis.button-disabled { cursor: default; }
            #wpz_autothumb_error, .autothumb_error { background-color: #ffffe0; padding: 5px 8px; border: 1px solid #e6db55; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; margin: 0; }
            #wpz_autothumb_error strong, .autothumb_error strong { display: inline-block; margin-bottom: 3px; }
            #wpz_autothumb_error small#wpz_autothumb_remind, .autothumb_error small { display: block; line-height: 1.5; color: #a19a3c; margin-top: 8px; }
            #wpz_ajax_loading { display: block; position: absolute; left: 0; right: 0; z-index: 100; text-align: center; text-shadow: 0 0 5px #fff, 0 0 5px #fff, 0 0 5px #fff, 0 0 5px #fff, 0 0 5px #fff; color: #000; }
        </style><?php
    }


    /**
     * All the JavaScript to make all the AJAX goodness work
     */
    public static function admin_newpost_foot() {
        ?><script type="text/javascript">
            var wpzVideoUrlInputTimeout,
                    wpzValidIframeRegex = /<iframe[^>]* src="[^"]+"[^>]*><\/iframe>/i; // This isn't super strict... It just loosely checks to see if the string kinda looks like it contains an embed code.

            var wpz_is_valid_url = function(str) {
                var pattern = new RegExp(/^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/, 'i');
                return pattern.test(str);
            };

            jQuery(function($){
                $('<div id="wpz_autothumb"><small id="wpz_ajax_loading" style="display:none">Loading...</small><p id="wpz_autothumb_error" class="updated" style="display:none"><?php _e('<strong>NOTICE!&nbsp;&nbsp;Unable to fetch video thumbnail</strong><br/>Either an invalid embed code was provided, or there is no thumbnail available for the specified video&hellip;<br/><small id="wpz_autothumb_remind"><strong>REMINDER:</strong> You can always manually upload a featured image via the WordPress Media Uploader.</small>', 'wpzoom'); ?></p><p id="wpzoom_autothumb_preview"><img src=""/><small id="wpz_usethis" class="button">Use This as the Featured Image</small></p></div>')
                    .insertAfter('#wpzoom_post_embed_code');

                $('#wpzoom_autothumb_preview img').on('load', function(){
                    $('#wpz_ajax_loading, #wpz_autothumb_error').hide();
                    $('#wpzoom_autothumb_preview').animate({height:'show',opacity:'show'});
                });

                $('#wpzoom_post_embed_code').on('input', function(){
                    clearTimeout(wpzVideoUrlInputTimeout);

                    if('' != (val = $.trim($('#wpzoom_post_embed_code').val())) && wpzValidIframeRegex.test(val)) {
                        $('#wpz_ajax_loading').fadeIn();

                        wpzVideoUrlInputTimeout = setTimeout(WPZVideoUrlOnInput, 1000);
                    } else {

                        if (wpz_is_valid_url(val)) {
                            wp.ajax.post(
                                'parse-embed',
                                {
                                    'post_ID': $('#post_ID').val(),
                                    'shortcode': '[embed]' + val + '[/embed]'
                                }
                            ).done(function (response) {
                                jQuery('#wpzoom_post_embed_code').val(response.body);
                                wpzVideoUrlInputTimeout = setTimeout(WPZVideoUrlOnInput, 1000);
                            }).fail(function () {
                                WPZRemovePreviewImage();
                                jQuery('#wpz_ajax_loading').hide();
                                jQuery('#wpz_autothumb_error').show();
                            });

                        } else {
                            $('#wpz_ajax_loading, #wpz_autothumb_error').hide();
                            WPZRemovePreviewImage();

                            if (!!val) {
                                $('#wpz_autothumb_error').show();
                            }
                        }
                    }
                }).triggerHandler('input');

                $('#wpz_usethis').on('click', WPZUseThisOnClick);

                $('#postimagediv').on('click', '#remove-post-thumbnail', WPZEnableSetFeaturedButton);
            });

            // This is called onInput if an actual embed code is provided
            function WPZVideoUrlOnInput() {
                var embed = jQuery.trim(jQuery('#wpzoom_post_embed_code').val());

                jQuery.ajax({
                    url: ajaxurl,
                    type: 'post',
                    data: { action: 'wpzoom_autothumb_get', wpzoom_autothumb_embedcode: embed, wpzoom_autothumb_postid: jQuery('#post_ID').val() },
                    dataType: 'json',
                    complete: function(xhr,status){
                        var response = xhr.responseText;

                        if(response == 'ERROR') {
                            WPZRemovePreviewImage();
                            jQuery('#wpz_ajax_loading').hide();
                            jQuery('#wpz_autothumb_error').show();
                            return;
                        }

                        response = jQuery.parseJSON(response);

                        var thumb_url = typeof response.thumb_url !== 'undefined' ? response.thumb_url : '',
                                is_featured = typeof response.is_already_featured !== 'undefined' ? response.is_already_featured : false;

                        if(thumb_url != '') {
                            jQuery('#wpzoom_autothumb_preview img').attr('src', '' + thumb_url);

                            if(is_featured == true) {
                                WPZDisableSetFeaturedButton();
                            } else {
                                WPZEnableSetFeaturedButton();
                            }
                        } else {
                            WPZRemovePreviewImage();
                        }

                        return;
                    }
                });

                return;
            }

            // This is called when the "Use This as the Featured Image" button is clicked
            function WPZUseThisOnClick() {
                if('' != (embed = jQuery.trim(jQuery('#wpzoom_post_embed_code').val()))) {
                    jQuery.ajax({
                        url: ajaxurl,
                        type: 'post',
                        data: {
                                action: 'wpzoom_autothumb_attach',
                                wpzoom_autothumb_embedcode: embed,
                                wpzoom_autothumb_postid: jQuery('#post_ID').val(),
                                wpzoom_autothumb_nonce: '<?php global $post; echo wp_create_nonce('wpzoom_attach_thumbnail-' . $post->ID); ?>'
                                    },
                        dataType: 'text',
                        complete: function(xhr,status){
                            var response = jQuery.trim(xhr.responseText);

                            if(response != 'false' && response > 0) {
                                WPZSetAsThumbnail(response, '<?php echo wp_create_nonce('set_post_thumbnail-' . $post->ID); ?>');
                            }

                            return;
                        }
                    });
                }

                return;
            }

            // Enable the "Use This as the Featured Image" button
            function WPZEnableSetFeaturedButton() {
                jQuery('#wpz_usethis')
                    .html('<?php _e('Use This as the Featured Image', 'wpzoom'); ?>')
                    .off('click', WPZUseThisOnClick)
                    .on('click', WPZUseThisOnClick)
                    .removeClass('button-disabled');
            }

            // Disable the "Use This as the Featured Image" button
            function WPZDisableSetFeaturedButton() {
                jQuery('#wpz_usethis')
                    .html('<?php _e('This is the Featured Image', 'wpzoom'); ?>')
                    .off('click', WPZUseThisOnClick)
                    .addClass('button-disabled');
            }

            // Hide/Remove the preview image
            function WPZRemovePreviewImage() {
                jQuery('#wpzoom_autothumb_preview').hide().removeAttr('src');
            }

            // Almost the same as the core WPSetAsThumbnail function
            function WPZSetAsThumbnail(id, nonce) {
                jQuery.post(ajaxurl, {
                    action: 'set-post-thumbnail',
                    post_id: jQuery('#post_ID').val(),
                    thumbnail_id: id,
                    _ajax_nonce: nonce,
                    cookie: encodeURIComponent(document.cookie)
                }, function(str){
                    var win = window.dialogArguments || opener || parent || top;

                    if(str != '0') {
                        win.WPSetThumbnailID(id);
                        win.WPSetThumbnailHTML(str);
                        WPZDisableSetFeaturedButton();
                    }
                }
                );
            }
        </script><?php
    }

    /**
     * Fetches the thumbnail URL based on a given video URL using oEmbed
     */
    public static function fetch_video_thumbnail($embed_url, $post_id) {
        $embed_url = trim($embed_url);
        $post_id = intval($post_id);

        if(empty($embed_url) || filter_var($embed_url, FILTER_VALIDATE_URL) === false || empty($post_id) || $post_id < 1) return false;

        if (false !== ($id=parent::extract_video_id($embed_url)) && $id['provider'] == 'youtube') {
            $output['thumb_url'] = self::get_youtube_thumbnail($id['id']);
        } else {
            $url = parent::convert_embed_url($embed_url);
            if($url === false) return false;

            require_once(ABSPATH . WPINC . '/class-oembed.php');
            $oembed = _wp_oembed_get_object();

            $provider = $oembed->get_provider($url);
            if(!$provider) return false;

            $data = $oembed->fetch($provider, $url);
            if(!$data) return false;

            $output['thumb_url'] = isset($data->thumbnail_url) && !empty($data->thumbnail_url) ? $data->thumbnail_url : '';
        }

        $output['is_already_featured'] = self::thumb_isset_featured($output['thumb_url'], $post_id);

        return $output;
    }

    /**
     * Tries to get the thumbnail image for a YouTube video
     */
    public static function get_youtube_thumbnail($video_id)
    {
        $output = '';

        $size = (class_exists('option') && in_array(option::get('video_api_size'), array('Small', 'Medium', 'Large'))) ? strtolower('' . option::get('video_api_size')) : null;
        $youtube_sizes = array('highresolution' => 'maxresdefault', 'large' => 'sddefault', 'medium' => 'hqdefault', 'small' => 'mqdefault');
        $is_size = empty($youtube_sizes[$size]) ? true : $youtube_sizes[$size];

        foreach (self::$youtube_thumbnail_sizes as $size) {
            $url = sprintf('http%s://img.youtube.com/vi/%s/%s.jpg', (is_ssl() ? 's' : ''), $video_id, $size);

            if (false !== ($img = getimagesize($url)) && is_array($img) && $is_size == $size) {
                $output = $url;
                break;
            }
        }

        return $output;
    }

    /**
     * Downloads and attaches the given remote thumbnail to the given post and returns the ID
     */
    public static function attach_remote_video_thumb($thumb_url, $post_id, $size = null) {
        if(!current_user_can('upload_files')) return false;

        $thumb_url = trim($thumb_url);
        $post_id = intval($post_id);

        if(empty($thumb_url) || filter_var($thumb_url, FILTER_VALIDATE_URL) === false || empty($post_id) || $post_id < 1) return false;

        if(is_null($size)) {
            $fetch = self::fetch_video_thumbnail($thumb_url, $post_id);
            if($fetch === false || !isset($fetch['thumb_url']) || empty($fetch['thumb_url'])) return false;
            $url = $fetch['thumb_url'];
        } elseif($size == 'small' || $size == 'medium' || $size == 'large') {
            $fetch = parent::fetch_extended_video_data($post_id);
            if($fetch === false) return false;

            $small = isset($fetch['thumbnail']['sqDefault']) ? $fetch['thumbnail']['sqDefault'] : ( isset($fetch['thumbnail_small']) ? $fetch['thumbnail_small'] : false );
            $medium = isset($fetch['thumbnail']['mqDefault']) ? $fetch['thumbnail']['mqDefault'] : ( isset($fetch['thumbnail_medium']) ? $fetch['thumbnail_medium'] : false );
            $large = isset($fetch['thumbnail']['hqDefault']) ? $fetch['thumbnail']['hqDefault'] : ( isset($fetch['thumbnail_large']) ? $fetch['thumbnail_large'] : false );

            if($small === false && $medium === false && $large === false) return false;

            if($size == 'small') {
                return $small !== false ? $small : ( $medium !== false ? $medium : ( $large !== false ? $large : false ) );
            } elseif($size == 'medium') {
                return $medium !== false ? $medium : ( $small !== false ? $small : ( $large !== false ? $large : false ) );
            } elseif($size == 'large') {
                return $large !== false ? $large : ( $medium !== false ? $medium : ( $small !== false ? $small : false ) );
            }
        } else {
            return false;
        }

        if(false === ($id=self::thumb_attachment_exists($url, $post_id)) || $id < 1) {
            $id = self::media_sideload_image($url, $post_id);
            if(!is_wp_error($id) && $id !== false && $id > 0) {
                add_post_meta($id, '_wpz_original_thumb_url', $url);
                return $id;
            } else {
                return false;
            }
        }

        return $id !== false && $id > 0 ? $id : false;
    }

    /**
     * Checks to see if the given thumbnail is already attached to the given post and returns the ID
     */
    public static function thumb_attachment_exists($thumb_url, $post_id) {
        $thumb_url = trim($thumb_url);
        $post_id = intval($post_id);

        if(empty($thumb_url) || filter_var($thumb_url, FILTER_VALIDATE_URL) === false || empty($post_id) || $post_id < 1) return false;

        $db = get_children(array(
            'post_type' => 'attachment',
            'post_parent' => $post_id,
            'post_mime_type' => 'image',
            'meta_key' => '_wpz_original_thumb_url',
            'meta_value' => $thumb_url,
            'numberposts' => 1
        ));

        if(empty($db)) return false;

        foreach($db as $attachment_id => $attachment) $id = $attachment_id;

        return !empty($id) && $id > 0 ? $id : false;
    }


    /**
     * Checks to see if the given thumbnail is currently set as the featured image for the given post
     */
    public static function thumb_isset_featured($thumb_url, $post_id) {
        $thumb_url = trim($thumb_url);
        $post_id = intval($post_id);

        if(empty($thumb_url) || filter_var($thumb_url, FILTER_VALIDATE_URL) === false || empty($post_id) || $post_id < 1) return false;

        $attachment_id = self::thumb_attachment_exists($thumb_url, $post_id);
        if($attachment_id === false || $attachment_id < 1) return false;

        $current_featured = get_post_thumbnail_id($post_id);
        return $current_featured == $attachment_id;
    }

    /**
     * Pretty much the same as the core media_sideload_image() function but with just a couple changes
     */
    public static function media_sideload_image($file, $post_id) {
        if ( ! empty($file) ) {
            require_once(ABSPATH . 'wp-admin/includes/image.php');
            require_once(ABSPATH . 'wp-admin/includes/file.php');
            require_once(ABSPATH . 'wp-admin/includes/media.php');

            // Download file to temp location
            $tmp = download_url( $file );

            // Set variables for storage
            // fix file filename for query strings
            preg_match('/[^\?]+\.(jpg|JPG|jpe|JPE|jpeg|JPEG|gif|GIF|png|PNG)/', $file, $matches);
            $file_array['name'] = basename($matches[0]);
            $file_array['tmp_name'] = $tmp;

            // If error storing temporarily, unlink
            if ( is_wp_error( $tmp ) ) {
                @unlink($file_array['tmp_name']);
                $file_array['tmp_name'] = '';
            }

            // do the validation and storage stuff
            $id = media_handle_sideload( $file_array, $post_id );
            // If error storing permanently, unlink
            if ( is_wp_error($id) ) {
                @unlink($file_array['tmp_name']);
                return $id;
            }

            return $id;
        }

        return false;
    }

    /**
     * For use in the get_the_image plugin from the framework. Returns the remote video thumbnail URL for a given post
     */
    public static function gettheimage_url($post_id) {
        $post_id = intval($post_id);
        if(empty($post_id) || $post_id < 1) return false;

        $embed_code = get_post_meta($post_id, 'wpzoom_post_embed_code', true);
        if(empty($embed_code)) return false;

        $url = parent::extract_url_from_embed(trim($embed_code));
        if($url === false) return false;

        $size = /*class_exists('option') && in_array(option::get('video_api_size'), array('Small', 'Medium', 'Large')) ? strtolower(''.option::get('video_api_size')) :*/ null;
        $attachment_id = self::attach_remote_video_thumb($url, $post_id, $size);
        if($attachment_id === false || $attachment_id < 1) return false;

        $attachment_image_src = wp_get_attachment_image_src($attachment_id);
        return $attachment_image_src !== false && is_array($attachment_image_src) && isset($attachment_image_src[0]) && !empty($attachment_image_src[0]) ? array('src' => ''.$attachment_image_src[0]) : false;
    }
}
