/* 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>`);
            console.log("DEBUG: appending audio=", args.audio, " to element=", args.element, "  ...");
            $(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>'
            );
        },
        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;
    }
};

