/*
* Youtube Embed Plugin
*
* @author Jonnas Fonini <jonnasfonini@gmail.com>
* @version 2.1.18
*/

/* global CKEDITOR */

(function () {
    'use strict';

    CKEDITOR.plugins.add('youtube', {
        lang: ['en', 'bg', 'pt', 'pt-br', 'ja', 'hu', 'it', 'fr', 'tr', 'ru', 'de', 'ar', 'nl', 'pl', 'vi', 'zh', 'el', 'he', 'es', 'nb', 'nn', 'fi', 'et', 'sk', 'cs', 'ko', 'eu', 'uk'],
        init: function (editor) {
            editor.addCommand('youtube', new CKEDITOR.dialogCommand('youtube', {
                allowedContent: 'div{*}(*); iframe{*}[!width,!height,!src,!frameborder,!allowfullscreen,!allow]; object param[*]; a[*]; img[*]'
            }));

            editor.ui.addButton('Youtube', {
                label: editor.lang.youtube.button,
                toolbar: 'insert',
                command: 'youtube',
                icon: this.path + 'images/icon.png'
            });

            CKEDITOR.dialog.add('youtube', function (instance) {
                var video,
                    disabled = editor.config.youtube_disabled_fields || [];

                function handleLinkChange (el, api) {
                    var video = ytVidId(el.getValue());
                    var time = ytVidTime(el.getValue());

                    if (el.getValue().length > 0) {
                        el.getDialog().getContentElement('youtubePlugin', 'txtEmbed').disable();
                    } else if (!disabled.length || !disabled.includes('txtEmbed')) {
                        el.getDialog().getContentElement('youtubePlugin', 'txtEmbed').enable();
                    }

                    if (video && time) {
                        var seconds = timeParamToSeconds(time);
                        var hms = secondsToHms(seconds);
                        el.getDialog().getContentElement('youtubePlugin', 'txtStartAt').setValue(hms);
                    }
                }

                function handleEmbedChange (el, api) {
                    if (el.getValue().length > 0) {
                        el.getDialog().getContentElement('youtubePlugin', 'txtUrl').disable();
                    } else {
                        el.getDialog().getContentElement('youtubePlugin', 'txtUrl').enable();
                    }
                }

                return {
                    title: editor.lang.youtube.title,
                    minWidth: 510,
                    minHeight: 200,
                    onShow: function () {
                        for (var i = 0; i < disabled.length; i++) {
                            this.getContentElement('youtubePlugin', disabled[i]).disable();
                        }
                    },
                    contents:
                        [{
                            id: 'youtubePlugin',
                            expand: true,
                            elements:
                                [{
                                    id: 'txtEmbed',
                                    type: 'textarea',
                                    label: editor.lang.youtube.txtEmbed,
                                    onChange: function (api) {
                                        handleEmbedChange(this, api);
                                    },
                                    onKeyUp: function (api) {
                                        handleEmbedChange(this, api);
                                    },
                                    validate: function () {
                                        if (this.isEnabled()) {
                                            if (!this.getValue()) {
                                                window.alert(editor.lang.youtube.noCode);
                                                return false;
                                            } else if (this.getValue().length === 0 || this.getValue().indexOf('//') === -1) {
                                                window.alert(editor.lang.youtube.invalidEmbed);
                                                return false;
                                            }
                                        }
                                    }
                                },
                                    {
                                        type: 'html',
                                        html: editor.lang.youtube.or + '<hr>'
                                    },
                                    {
                                        type: 'hbox',
                                        widths: ['70%', '15%', '15%'],
                                        children:
                                            [
                                                {
                                                    id: 'txtUrl',
                                                    type: 'text',
                                                    label: editor.lang.youtube.txtUrl,
                                                    onChange: function (api) {
                                                        handleLinkChange(this, api);
                                                    },
                                                    onKeyUp: function (api) {
                                                        handleLinkChange(this, api);
                                                    },
                                                    validate: function () {
                                                        if (this.isEnabled()) {
                                                            if (!this.getValue()) {
                                                                window.alert(editor.lang.youtube.noCode);
                                                                return false;
                                                            } else {
                                                                video = ytVidId(this.getValue());

                                                                if (this.getValue().length === 0 || video === false) {
                                                                    window.alert(editor.lang.youtube.invalidUrl);
                                                                    return false;
                                                                }
                                                            }
                                                        }
                                                    }
                                                },
                                                {
                                                    type: 'text',
                                                    id: 'txtWidth',
                                                    width: '60px',
                                                    label: editor.lang.youtube.txtWidth,
                                                    'default': editor.config.youtube_width != null ? editor.config.youtube_width : '640',
                                                    validate: function () {
                                                        if (this.getValue()) {
                                                            var width = Number(this.getValue());

                                                            if (isNaN(width)) {
                                                                window.alert(editor.lang.youtube.invalidWidth);
                                                                return false;
                                                            }
                                                        } else {
                                                            window.alert(editor.lang.youtube.noWidth);
                                                            return false;
                                                        }
                                                    }
                                                },
                                                {
                                                    type: 'text',
                                                    id: 'txtHeight',
                                                    width: '60px',
                                                    label: editor.lang.youtube.txtHeight,
                                                    'default': editor.config.youtube_height != null ? editor.config.youtube_height : '360',
                                                    validate: function () {
                                                        if (this.getValue()) {
                                                            var height = Number(this.getValue());

                                                            if (isNaN(height)) {
                                                                window.alert(editor.lang.youtube.invalidHeight);
                                                                return false;
                                                            }
                                                        } else {
                                                            window.alert(editor.lang.youtube.noHeight);
                                                            return false;
                                                        }
                                                    }
                                                }
                                            ]
                                    },
                                    {
                                        type: 'hbox',
                                        widths: ['55%', '45%'],
                                        children:
                                            [
                                                {
                                                    id: 'chkResponsive',
                                                    type: 'checkbox',
                                                    label: editor.lang.youtube.txtResponsive,
                                                    'default': editor.config.youtube_responsive != null ? editor.config.youtube_responsive : false
                                                },
                                                {
                                                    id: 'chkNoEmbed',
                                                    type: 'checkbox',
                                                    label: editor.lang.youtube.txtNoEmbed,
                                                    'default': editor.config.youtube_noembed != null ? editor.config.youtube_noembed : false
                                                }
                                            ]
                                    },
                                    {
                                        type: 'hbox',
                                        widths: ['55%', '45%'],
                                        children:
                                            [
                                                {
                                                    id: 'chkRelated',
                                                    type: 'checkbox',
                                                    'default': editor.config.youtube_related != null ? editor.config.youtube_related : true,
                                                    label: editor.lang.youtube.chkRelated
                                                },
                                                {
                                                    id: 'chkOlderCode',
                                                    type: 'checkbox',
                                                    'default': editor.config.youtube_older != null ? editor.config.youtube_older : false,
                                                    label: editor.lang.youtube.chkOlderCode
                                                }
                                            ]
                                    },
                                    {
                                        type: 'hbox',
                                        widths: ['55%', '45%'],
                                        children:
                                            [
                                                {
                                                    id: 'chkPrivacy',
                                                    type: 'checkbox',
                                                    label: editor.lang.youtube.chkPrivacy,
                                                    'default': editor.config.youtube_privacy != null ? editor.config.youtube_privacy : false
                                                },
                                                {
                                                    id: 'chkAutoplay',
                                                    type: 'checkbox',
                                                    'default': editor.config.youtube_autoplay != null ? editor.config.youtube_autoplay : false,
                                                    label: editor.lang.youtube.chkAutoplay
                                                }
                                            ]
                                    },
                                    {
                                        type: 'hbox',
                                        widths: ['55%', '45%'],
                                        children:
                                            [
                                                {
                                                    id: 'txtStartAt',
                                                    type: 'text',
                                                    label: editor.lang.youtube.txtStartAt,
                                                    validate: function () {
                                                        if (this.getValue()) {
                                                            var str = this.getValue();

                                                            if (!/^(?:(?:([01]?\d|2[0-3]):)?([0-5]?\d):)?([0-5]?\d)$/i.test(str)) {
                                                                window.alert(editor.lang.youtube.invalidTime);
                                                                return false;
                                                            }
                                                        }
                                                    }
                                                },
                                                {
                                                    id: 'chkControls',
                                                    type: 'checkbox',
                                                    'default': editor.config.youtube_controls != null ? editor.config.youtube_controls : true,
                                                    label: editor.lang.youtube.chkControls
                                                }
                                            ]
                                    }
                                ]
                        }
                        ],
                    onOk: function () {
                        var content = '';
                        var responsiveStyle = '';

                        if (this.getContentElement('youtubePlugin', 'txtEmbed').isEnabled()) {
                            content = this.getValueOf('youtubePlugin', 'txtEmbed');
                        } else {
                            var url = 'https://', params = [], startSecs,
                                paramAutoplay = '';
                            var width = this.getValueOf('youtubePlugin', 'txtWidth');
                            var height = this.getValueOf('youtubePlugin', 'txtHeight');

                            if (this.getContentElement('youtubePlugin', 'chkPrivacy').getValue() === true) {
                                url += 'www.youtube-nocookie.com/';
                            } else {
                                url += 'www.youtube.com/';
                            }

                            url += 'embed/' + video;

                            if (this.getContentElement('youtubePlugin', 'chkRelated').getValue() === false) {
                                params.push('rel=0');
                            }

                            if (this.getContentElement('youtubePlugin', 'chkAutoplay').getValue() === true) {
                                params.push('autoplay=1');
                                paramAutoplay = 'autoplay';
                            }

                            if (this.getContentElement('youtubePlugin', 'chkControls').getValue() === false) {
                                params.push('controls=0');
                            }

                            startSecs = this.getValueOf('youtubePlugin', 'txtStartAt');

                            if (startSecs) {
                                var seconds = hmsToSeconds(startSecs);

                                params.push('start=' + seconds);
                            }

                            if (params.length > 0) {
                                url = url + '?' + params.join('&');
                            }

                            if (this.getContentElement('youtubePlugin', 'chkResponsive').getValue() === true) {
                                content += '<div class="youtube-embed-wrapper" style="position:relative;padding-bottom:56.25%;padding-top:30px;height:0;overflow:hidden">';
                                responsiveStyle = 'style="position:absolute;top:0;left:0;width:100%;height:100%"';
                            }

                            if (this.getContentElement('youtubePlugin', 'chkOlderCode').getValue() === true) {
                                url = url.replace('embed/', 'v/');
                                url = url.replace(/&/g, '&amp;');

                                if (url.indexOf('?') === -1) {
                                    url += '?';
                                } else {
                                    url += '&amp;';
                                }
                                url += 'hl=' + (this.getParentEditor().config.language ? this.getParentEditor().config.language : 'en') + '&amp;version=3';

                                content += '<object width="' + width + '" height="' + height + '" ' + responsiveStyle + '>';
                                content += '<param name="movie" value="' + url + '"></param>';
                                content += '<param name="allowFullScreen" value="true"></param>';
                                content += '<param name="allowscriptaccess" value="always"></param>';
                                content += '<embed src="' + url + '" type="application/x-shockwave-flash" ';
                                content += 'width="' + width + '" height="' + height + '" ' + responsiveStyle + ' allowscriptaccess="always" ';
                                content += 'allowfullscreen="true"></embed>';
                                content += '</object>';
                            } else if (this.getContentElement('youtubePlugin', 'chkNoEmbed').getValue() === true) {
                                var imgSrc = 'https://img.youtube.com/vi/' + video + '/sddefault.jpg';
                                content += '<a href="' + url + '" ><img width="' + width + '" height="' + height + '" src="' + imgSrc + '" ' + responsiveStyle + '/></a>';
                            } else {
                                content += '<iframe ' + (paramAutoplay ? 'allow="' + paramAutoplay + ';" ' : '') + 'width="' + width + '" height="' + height + '" src="' + url + '" ' + responsiveStyle;
                                content += 'frameborder="0" allowfullscreen></iframe>';
                            }

                            if (this.getContentElement('youtubePlugin', 'chkResponsive').getValue() === true) {
                                content += '</div>';
                            }
                        }

                        var element = CKEDITOR.dom.element.createFromHtml(content);
                        var instance = this.getParentEditor();
                        instance.insertElement(element);
                    }
                };
            });
        }
    });
})();

/**
 * JavaScript function to match (and return) the video Id
 * of any valid Youtube Url, given as input string.
 * @author: Stephan Schmitz <eyecatchup@gmail.com>
 * @url: http://stackoverflow.com/a/10315969/624466
 */
function ytVidId (url) {
    'use strict';

    var p = /^(?:https?:\/\/)?(?:(?:www|m).)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))((\w|-){11})(?:\S+)?$/;
    return (url.match(p)) ? RegExp.$1 : false;
}

/**
 * Matches and returns time param in YouTube Urls.
 */
function ytVidTime (url) {
    'use strict';

    var p = /t=([0-9hms]+)/;
    return (url.match(p)) ? RegExp.$1 : false;
}

/**
 * Converts time in hms format to seconds only
 */
function hmsToSeconds (time) {
    'use strict';

    var arr = time.split(':'), s = 0, m = 1;

    while (arr.length > 0) {
        s += m * parseInt(arr.pop(), 10);
        m *= 60;
    }

    return s;
}

/**
 * Converts seconds to hms format
 */
function secondsToHms (seconds) {
    'use strict';

    var h = Math.floor(seconds / 3600);
    var m = Math.floor((seconds / 60) % 60);
    var s = seconds % 60;

    var pad = function (n) {
        n = String(n);
        return n.length >= 2 ? n : '0' + n;
    };

    if (h > 0) {
        return pad(h) + ':' + pad(m) + ':' + pad(s);
    } else {
        return pad(m) + ':' + pad(s);
    }
}

/**
 * Converts time in youtube t-param format to seconds
 */
function timeParamToSeconds (param) {
    'use strict';

    var componentValue = function (si) {
        var regex = new RegExp('(\\d+)' + si);
        return param.match(regex) ? parseInt(RegExp.$1, 10) : 0;
    };

    return componentValue('h') * 3600 + componentValue('m') * 60 + componentValue('s');
}

/**
 * Converts seconds into youtube t-param value, e.g. 1h4m30s
 */
function secondsToTimeParam (seconds) {
    'use strict';

    var h = Math.floor(seconds / 3600);
    var m = Math.floor((seconds / 60) % 60);
    var s = seconds % 60;
    var param = '';

    if (h > 0) {
        param += h + 'h';
    }

    if (m > 0) {
        param += m + 'm';
    }

    if (s > 0) {
        param += s + 's';
    }

    return param;
}
