/* Copyright (C) 2013, 2014 Tilman Kranz <tilt@linuxfoo.de>
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
 * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
 * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
 * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
 * THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE */

var MyPlayer = function(_args) {
    var failed = false,
        detached = false,
        player = null,
        args_default = {
            autoplay: false,
            css: { "height": "500px" },
            detachable: true,
            element: "body",
            id3: false,
            list: [],
            loop: true,
            mode: "mp3url",
            shuffle: false,
            waveform: false
        },
        args = (_args===undefined) ? args_default : $.extend({}, args_default, _args),
        mimeTypeFromSrc = function(src) {
            var extension = src.split(".").pop().toLowerCase();

            var types = {
                "3g2": "video/3gpp2",
                "3gp": "video/3gpp",
                "7z": "application/x-7z-compressed",
                "aac": "audio/aac",
                "abw": "application/x-abiword",
                "arc": "application/x-freearc",
                "avi": "video/x-msvideo",
                "azw": "application/vnd.amazon.ebook",
                "bin": "application/octet-stream",
                "bmp": "image/bmp",
                "bz": "application/x-bzip",
                "bz2": "application/x-bzip2",
                "cda": "application/x-cdf",
                "csh": "application/x-csh",
                "css": "text/css",
                "csv": "text/csv",
                "doc": "application/msword",
                "eot": "application/vnd.ms-fontobject",
                "epub": "application/epub+zip",
                "gif": "image/gif",
                "gz": "application/gzip",
                "htm": "text/html",
                "html": "text/html",
                "ico": "image/vnd.microsoft.icon",
                "ics": "text/calendar",
                "jar": "application/java-archive",
                "jpeg": "image/jpeg",
                "jpg": "image/jpeg",
                "js": "text/javascript",
                "json": "application/json",
                "jsonld": "application/ld+json",
                "mid": "audio/midi audio/x-midi",
                "midi": "audio/midi audio/x-midi",
                "mjs": "text/javascript",
                "mp3": "audio/mpeg",
                "mp4": "video/mp4",
                "mpeg": "video/mpeg",
                "mpkg": "application/vnd.apple.installer+xml",
                "odp": "application/vnd.oasis.opendocument.presentation",
                "ods": "application/vnd.oasis.opendocument.spreadsheet",
                "odt": "application/vnd.oasis.opendocument.text",
                "oga": "audio/ogg",
                "ogv": "video/ogg",
                "ogx": "application/ogg",
                "opus": "audio/opus",
                "otf": "font/otf",
                "pdf": "application/pdf",
                "php": "application/x-httpd-php",
                "png": "image/png",
                "ppt": "application/vnd.ms-powerpoint",
                "rar": "application/vnd.rar",
                "rtf": "application/rtf",
                "sh": "application/x-sh",
                "svg": "image/svg+xml",
                "swf": "application/x-shockwave-flash",
                "tar": "application/x-tar",
                "tif": "image/tiff",
                "tiff": "image/tiff",
                "ts": "video/mp2t",
                "ttf": "font/ttf",
                "txt": "text/plain",
                "vsd": "application/vnd.visio",
                "wav": "audio/wav",
                "weba": "audio/webm",
                "webm": "video/webm",
                "webp": "image/webp",
                "woff": "font/woff",
                "woff2": "font/woff2",
                "xhtml": "application/xhtml+xml",
                "xls": "application/vnd.ms-excel",
                "xml": "application/xml",
                "xul": "application/vnd.mozilla.xul+xml",
                "zip": "application/zip"
            };

            return types[extension] || "application/octet-stream";
        },
        createAudio = function() {
            var autoplay = args.autoplay ? 'autoplay="true"' : '';
            var styles = [];
            var style;
            var key;

            for (key in args.css) {
                var value = args.css[key];
                styles.push(`${key}: ${value}`);
            }

            style = styles.join(" ");
            args.audio = $(`<audio id="myplayer" controls="controls" style="${style}" ${autoplay}></audio>`);
            $(args.element).append(args.audio);
        },
        readId3 = function() {
            $(args.element).find('ul.mejs li').each(function(i, track){
                var url = $(track).attr('data-url');

                $(track).prepend('<span class="ajaxLoader">&nbsp;</span>&nbsp;');

                jsmediatags.read(url, {
                    onSuccess: function(tag) {
                        var tags = tag.tags;
                        var track_title;

                        if(typeof(tags.title)!='undefined') {
                             track_title = tags.title;
                        }
                        else {
                             track_title = url;
                        }

                        if(typeof(tags.artist)!='undefined') {
                             track_title = tags.artist + ' - ' + track_title;
                        }

                        $(args.element).find('ul.mejs li').each(function(j, _track){
                             if(i==j) {
                                  $(_track).html(track_title);
                             }
                        });
                    }
                });
            });
        },
        playerCreated = function(mediaElement, originalNode, instance) {
            restoreParams();

            if(args.shuffle) {
                instance.shuffleCallback();
            }

            if(args.loop) {
                instance.loopCallback();
            }

            if(args.id3) {
                readId3();
            }
        },
        createPlayer = function() {
            player = new MediaElementPlayer(
                "myplayer", {
                    success: playerCreated,
                    features: [
                         'playpause',
                         'current',
                         'progress',
                         'duration',
                         'volume',
                         'playlist',
                         'prevtrack',
                         'nexttrack',
                         'shuffle',
                         'loop'
                    ]
                }
            );

            $(args.element).append(
                '<p class="playerDetached" style="display: none;">'+
                    'The player is currently detached.'+
                '</p>'
            );

            $(args.element).append(iconSprite);
        },
        param = function(name) {
            var query = window.location.search.substring(1);
            var vars = query.split("&");

            for(i=0; i<vars.length; i++) {
                var pair = vars[i].split("=");

                if(pair[0] == name) {
                    return pair[1];
                }
            }

            return false;
        },
        setupDetach = function() {
            if(!args.detachable) {
                return;
            }

            var popup = function(url) {
                player.pause();
                $('.mejs-audio').hide();
                $('.playerDetached').show();

                var playerWindow = window.open(
                    url, 'myplayer',
                    'height='+ Math.max($(args.element).height(), 298)+','+
                    'width='+408+','+
                    'resizable=false'
                );

                if(window.focus) {
                    playerWindow.focus();
                }

                $("iframe",top.document).height(20);

                return false;
            };

            if(param('popup')==false) {
                $('.mejs-controls').append(
                    '<div id="popupButton" '+
                         'class="popupButton">'+
                              '<button '+
                                    'title="Open in separate window" '+
                                    'type="button">'+
                              '</button>'+
                    '</div>'
                );

                $('.popupButton button').click(function(){
                    var currentTime = player.getCurrentTime();
                    var volume = player.getVolume();
                    var paused = player.media.paused;
                    var trackNo = 0;

                    $(args.element).find('ul.mejs li').each(function(i){
                        if($(this).hasClass('current')) {
                             trackNo = i;
                        }
                    });

                    popup(
                        $(location).attr('href')+'?'+
                            'popup&'+
                            'paused='+paused+'&'+
                            'currentTime='+currentTime+'&'+
                            'volume='+volume+'&'+
                            'trackNo='+trackNo
                    );
                });
            }
            else {
                var windowHeight = $(window).height();

                window.onbeforeunload = function(){
                    $("iframe", opener.top.document).height(windowHeight);
                    $('.mejs-audio', opener.document).show();
                    $('.playerDetached', opener.document).hide();
                };
            }
        },
        restoreParams = function() {
            if(!detached) {
                return;
            }

            var paused = (param('paused') && param('paused')=='true');
            var currentTime = param('currentTime') ? parseFloat(param('currentTime')) : 0.0;
            var volume = param('volume') ? parseFloat(param('volume')) : 1.0;
            var trackNo = param('trackNo') ? parseInt(param('trackNo')) : 0;

            player.setVolume(volume);

            $(args.element).find('ul.mejs li').each(function(i){
                if(i==trackNo) {
                    player.playTrack($(this));
                    player.setCurrentTime(currentTime);
                }
            });

            if(paused) {
                player.pause();
            }
        };

    if(param('popup')!==false) {
        detached = true;

        $('body').html(
            '<div ' +
                'id="myplayer" ' +
                'style="' +
                    'width: ' + $(args.element).width() + 'px; '+
                    'height: ' + $(args.element).height() + ' px;'+
            '"></div>'
        );

        args.element = '#myplayer';
    }

    if(args.mode=='mp3url') {
        console.log("args.mode=", args.mode);
        var mp3url = (typeof args.mp3url === "undefined")
            ? $(location).attr('href').replace(/\?.*/, '').replace(/\/[^\/]+\/?$/, '')
            : args.mp3url;

        $.ajax({
            url: mp3url,
            type: 'GET',
            success: function(res) {
                var doc;
                var head;

                doc = document.createElement('html');

                createAudio();
                doc.innerHTML = res;

                head = $(doc).find('a').each(function(idx,item) {
                    var src = $(item).attr('href');

                    if(src.match(/\.mp3$/)) {
                        var url = mp3url+'/'+src;
                        var title = item.innerHTML;
                        var type = "audio/mpeg";

                        args.audio.append(`<source src="${url}" type="${type}" title="${title}"/>`);
                     }
                });

                createPlayer();
                setupDetach();
            }
        });
    }
    else if(args.mode=='m3u') {
        var m3u = (typeof args.m3u === "undefined")
            ? $(location).attr('href').replace(/\?.*/, '').replace(/\/[^\/]+\/?$/, '/play.m3u')
            : args.m3u;

        createAudio();

        $.get(m3u, function(txt){
            var lines = txt.split("\n");
            var len = lines.length;
            var i = 0;

            while(i < len) {
                if(!lines[i].match(/^[ \t]*#/) && lines[i].match(/\.mp3$/)) {
                     var mp3 = lines[i];
                     var title = unescape(mp3.split('/').pop());
                     var type = "audio/mpeg";

                     args.audio.append(`<source src="${mp3}" type="${type}" title="${title}"/>`);
                }

                i++;
            }

            createPlayer();
            setupDetach();
        });
    }
    else if(args.mode=='list') {
        var len = args.list.length;
        var i = 0;

        createAudio();

        while(i < len) {
             var item = args.list[i];
             var type = typeof item;
             var src = '';
             var title = '';
             var type;

             if(item !== null && type === 'object') {
                 if(item.url) {
                     src = item.url;
                 }
                 else {
                     alert(`MyPlayer: item[${i}]: property "url" is missing.`);
                     i++;
                     continue;
                 }

                 if(item.title) {
                     title = item.title;
                 }
                 else {
                     title = url.replace(/(.*\/)?([^\/]+)/, '$2');
                 }
             }
             else if(type === 'string') {
                 src = item;
                 title = src;
             }
             else {
                 alert(`MyPlayer: item[${i}]: unsupported type=${type}.`);
                 i++;
                 continue;
             }

             type = mimeTypeFromSrc(src);

             args.audio.append(`<source src="${src}" type="${type}" title="${type}"/>`);

             i++;
        }

        createPlayer();
        setupDetach();
    }
    else {
        $(args.element).append(`<p>Unsupported mode ${args.mode}"</p>`);
        failed = true;
    }

    var iconSprite = `
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <symbol id="icon-captions" viewBox="0 0 18 14" xmlns="http://www.w3.org/2000/svg">
        <g fill="#fff">
            <path d="M-.67-4.08h14a2,2,0,0,1,2,2v10a2,2,0,0,1-2,2h-14a2,2,0,0,1-2-2v-10A2,2,0,0,1-.67-4.08Z" transform="translate(2.67 4.08)"/>
        </g>
        <g fill="#000">
            <path d="M2.88,6.67a2.81,2.81,0,0,1-2.1-1A3.91,3.91,0,0,1,.88.87c.5-.6,2-1.7,4.6.2l-.6.8c-1.4-1-2.6-1.1-3.3-.3a3,3,0,0,0-.1,3.5c.7.9,1.9.8,3.4-.1l.5.9a5.28,5.28,0,0,1-2.5.8Zm7.5,0a2.81,2.81,0,0,1-2.1-1,3.91,3.91,0,0,1,.1-4.8c.5-.6,2-1.7,4.6.2l-.5.8c-1.4-1-2.6-1.1-3.3-.3a3,3,0,0,0-.1,3.5c.7.9,1.9.8,3.4-.1l.5.9a6.07,6.07,0,0,1-2.6.8Z" transform="translate(2.67 4.08)"/>
        </g>
    </symbol>
    <symbol id="icon-chapters" viewBox="0 0 16.6 13" xmlns="http://www.w3.org/2000/svg"><path d="M1.5,0A1.54,1.54,0,0,1,3,1.5,1.54,1.54,0,0,1,1.5,3,1.54,1.54,0,0,1,0,1.5,1.47,1.47,0,0,1,1.5,0ZM6.6,0h8.5a1.47,1.47,0,0,1,1.5,1.5A1.54,1.54,0,0,1,15.1,3H6.6A1.47,1.47,0,0,1,5.1,1.5,1.37,1.37,0,0,1,6.6,0ZM1.5,5A1.54,1.54,0,0,1,3,6.5,1.54,1.54,0,0,1,1.5,8,1.54,1.54,0,0,1,0,6.5,1.47,1.47,0,0,1,1.5,5ZM6.6,5h8.5a1.47,1.47,0,0,1,1.5,1.5A1.54,1.54,0,0,1,15.1,8H6.6A1.47,1.47,0,0,1,5.1,6.5,1.37,1.37,0,0,1,6.6,5ZM1.5,10a1.5,1.5,0,0,1,0,3A1.54,1.54,0,0,1,0,11.5,1.47,1.47,0,0,1,1.5,10Zm5.1,0h8.5a1.47,1.47,0,0,1,1.5,1.5A1.54,1.54,0,0,1,15.1,13H6.6a1.47,1.47,0,0,1-1.5-1.5A1.37,1.37,0,0,1,6.6,10Z"/></symbol>
    <symbol id="icon-fullscreen" viewBox="0 0 17.8 17.8" xmlns="http://www.w3.org/2000/svg"><path d="M0,1A.94.94,0,0,1,1,0H6.4c.6,0,.7.3.3.7l-6,6C.3,7.1,0,7,0,6.4ZM0,16.8a.94.94,0,0,0,1,1H6.4c.6,0,.7-.3.3-.7l-6-6c-.4-.4-.7-.3-.7.3ZM17.8,1a.94.94,0,0,0-1-1H11.4c-.6,0-.7.3-.3.7l6,6c.4.4.7.3.7-.3Zm0,15.8a.94.94,0,0,1-1,1H11.4c-.6,0-.7-.3-.3-.7l6-6c.4-.4.7-.3.7.3Z"/></symbol>
    <symbol id="icon-unfullscreen" viewBox="0 0 17.8 17.8" xmlns="http://www.w3.org/2000/svg"><path d="M11.74,4.64a.94.94,0,0,0,1,1h4.1c.6,0,.7-.3.3-.7L12.44.24c-.4-.4-.7-.3-.7.3Zm-7.1,1a.94.94,0,0,0,1-1V.54c0-.6-.3-.7-.7-.3L.24,4.94c-.4.4-.3.7.3.7Zm1,7.1a.94.94,0,0,0-1-1H.54c-.6,0-.7.3-.3.7l4.7,4.7c.4.4.7.3.7-.3Zm7.1-1a.94.94,0,0,0-1,1v4.1c0,.5.3.7.7.3l4.7-4.7c.4-.4.3-.7-.3-.7Z"/></symbol>
    <symbol id="icon-mute" viewBox="0 0 17.55 17.03" xmlns="http://www.w3.org/2000/svg">
        <g stroke="none">
            <path d="M6.21,4.36a3,3,0,0,1-1.8.6H1.21a.94.94,0,0,0-1,1v5.7a.94.94,0,0,0,1,1h4.2c.3.2.5.4.8.6l3.5,2.6a.47.47,0,0,0,.8-.4V2.06a.47.47,0,0,0-.8-.4Z"/>
        </g>
        <g fill="none" stroke-linecap="round" stroke-width="1.5px">
            <path d="M13.11,1.18S17,.38,17,8.88s-3.9,7.8-3.9,7.8"/>
            <path d="M11.81,5.08s2.6-.4,2.6,3.8-2.6,3.9-2.6,3.9"/>
        </g>
    </symbol>
    <symbol id="icon-unmute" viewBox="0 0 18.2 17" xmlns="http://www.w3.org/2000/svg">
        <g stroke="none">
            <path d="M6.21,4.36a3,3,0,0,1-1.8.6H1.21a.94.94,0,0,0-1,1v5.7a.94.94,0,0,0,1,1h4.2c.3.2.5.4.8.6l3.5,2.6a.47.47,0,0,0,.8-.4V2.06a.47.47,0,0,0-.8-.4Z"/>
        </g>
        <g fill="none" stroke-linecap="round" stroke-width="2px">
            <path d="M12,5.55l5.4,5.4M12,11l5.4-5.4"/>
        </g>
    </symbol>
    <symbol id="icon-play" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg"><path d="M16.5 8.5c.3.1.4.5.2.8-.1.1-.1.2-.2.2l-11.4 7c-.5.3-.8.1-.8-.5V2c0-.5.4-.8.8-.5l11.4 7z"/></symbol>
    <symbol id="icon-pause" viewBox="0 0 14 16" xmlns="http://www.w3.org/2000/svg"><path d="M1,0H3.2a.94.94,0,0,1,1,1V15a.94.94,0,0,1-1,1H1a.94.94,0,0,1-1-1V1A1,1,0,0,1,1,0Zm9.8,0H13a.94.94,0,0,1,1,1V15a.94.94,0,0,1-1,1H10.8a.94.94,0,0,1-1-1V1A1,1,0,0,1,10.8,0Z"/></symbol>
    <symbol id="icon-replay" viewBox="0 0 17.52 15.97" xmlns="http://www.w3.org/2000/svg"><path d="M16.7,7.27a.81.81,0,0,1-.9.7c-.1,0-.2,0-.2-.1l-4.9-1.8c-.5-.2-.6-.6-.1-.8l6.2-3.6c.5-.3.8-.1.7.5l-.8,5.1Z"/><path d="M8.1,13.77a5.92,5.92,0,0,1-2.9-.7A5.77,5.77,0,0,1,2,7.87a6.21,6.21,0,0,1,6.3-6A6.15,6.15,0,0,1,13.9,6l.1-.1L16.1,7A8.1,8.1,0,0,0,7,.07,8.24,8.24,0,0,0,0,8a8.06,8.06,0,0,0,4.3,7,10.21,10.21,0,0,0,3.8,1,8.24,8.24,0,0,0,6.6-3.3l-1.8-.9a7,7,0,0,1-4.8,2Z"/></symbol>
    <symbol id="icon-overlay-play" viewBox="0 0 80 80" xmlns="http://www.w3.org/2000/svg">
        <g fill="#333" stroke="#fff" stroke-width="5px">
            <path d="M2.5,40A37.5,37.5,0,1,1,40,77.5,37.51,37.51,0,0,1,2.5,40Z"/>
        </g>
        <g fill="#fff">
            <path d="M60.3,38a1,1,0,0,1,.6,1.4.9.9,0,0,1-.6.6L30,57.5c-1,.6-1.7.1-1.7-1v-35c0-1.1.8-1.5,1.7-1Z"/>
        </g>
    </symbol>
    <symbol id="icon-loading-spinner" viewBox="0 0 75.8 77.9" xmlns="http://www.w3.org/2000/svg">
        <g fill="#fff">
            <circle cx="38.8" cy="8.1" r="8.1"/>
            <g opacity="0.4">
                <circle cx="70.8" cy="40" r="5"/>
            </g>
            <g opacity="0.6">
                <circle cx="38.8" cy="71.9" r="6"/>
            </g>
            <g opacity="0.8">
                <circle cx="7" cy="40" r="7"/>
            </g>
            <g opacity="0.9">
                <circle cx="15.1" cy="17.3" r="7.5"/>
            </g>
            <g opacity="0.3">
                <circle cx="63.2" cy="17.1" r="4.5"/>
            </g>
            <g opacity="0.5">
                <circle cx="62.7" cy="63.8" r="5.5"/>
            </g>
            <g opacity="0.7">
                <circle cx="15.1" cy="63.8" r="6.5"/>
            </g>
        </g>
    </symbol>
</svg>`;
};

