(function($) {
    $.fn.psMediaPlayer = function(playlist, userOptions) {
        var defaultOptions,
            options,
            $playerInstance,
            $playerInterface,
            playlistInstance,
            $currentTrack = null,
            currentTrackId = false,
            playing = false;

        defaultOptions = {
            elem: null,
            autoPlay: false,
            fileTypes: [],
            jPlayer: {
                swfPath: "/plugins/mediaplayer/jPlayer/jquery.jplayer",
                supplied: "mp3",
                solution:'html, flash',
                errorAlerts: false,
                warningAlerts: false
            }
        };

        options = $.extend(true, {}, defaultOptions, userOptions);

        var construct = function () {
            if(!options.elem) {
                // no support for this yet
                $playerInstance = buildPlayer($('body'));
            }
            else {
                // $playerInstance is to be a jQuery var, if options.elem isn't, make it so.
                $playerInstance = options.elem instanceof jQuery ? options.elem : $(options.elem);
            }

            $playerInterface = $playerInstance.next();

            // setup playlist listeners
            $playerInterface.find('a.ps-previous').click(previousTrack);
            $playerInterface.find('a.ps-next').click(nextTrack);

            buildPlaylist();

            // setup control listeners
            $playerInstance.bind($.jPlayer.event.ready, setupListeners);

            // jPlayer expects type of files supplied to be set as comma
            // separated string of extension names. Build this value from
            // fileTypes option passed set when player is created.
            options.jPlayer.supplied = options.fileTypes.join(", ");

            // set ready callback on jPlayer to build the playlist
            // options.jPlayer.ready = buildPlaylist;
            options.jPlayer.ready = function () {setCurrentTrack(0)};

            $playerInstance.jPlayer(options.jPlayer);
        }

        var buildPlaylist = function () {
            current = 0;

            var playlistList = $$('ol');

            // build playlist list
            for(var i=0; i < playlist.tracks.length; i++) {
                var trackElem = $$('li',
                    $$('a',
                        $$('span', {'class':'play-icon'}),
                        $$('span', playlist.tracks[i].title, {'class':'title'}),
                    {'href':'#'}),
                {
                    'class': 'track track-'+i
                })

                // look for download and purchase links
                if(playlist.tracks[i].buy_link) {
                    trackElem.append($$('span', $$('a', 'Buy Now', {'href':'#'}), {'class': 'extras'}));
                }

                if(playlist.tracks[i].download_link) {
                    var downloadElem = $$('a', 'Download', {'href':'#'});
                    if(trackElem.find('span.extras').size() == 1) {
                        trackElem.find('span.extras').append(downloadElem);
                    }
                    else {
                        trackElem.append($$('span', {'class': 'extras'}).append(downloadElem));
                    }
                }

                playlistList.append(trackElem);
            }

            playlistList.find('li.track a:not("span.extras a")').click(onSelectTrack);
            playlistList.find('li span.extras a').click(onClickExtra);

            $playerInterface.find('div.ps-playlist').eq(0).html(playlistList);

            // set title and select first track in playlist..
            // Looks better for loading if we do this
            $playerInterface.find('li.track-0').addClass('selected');
            $playerInterface.find('.ps-title').html(playlist.tracks[0].title);
            $playerInterface.find('div.ps-album-art').html($$('img', {'src': playlist.tracks[0].art}));
        }

        var setCurrentTrack = function (trackId) {
            if(currentTrackId === trackId){ //&& not paused
                return;
            }

            // assign currentTrack from track's id
            currentTrackId = parseInt(trackId);
            $currentTrack = $playerInterface.find('li.track-'+currentTrackId);
            $currentTrack.addClass('selected');

            $playerInstance.jPlayer("setMedia", playlist.tracks[currentTrackId]);

            // update title in UI
            $playerInterface.find('.ps-title').html(playlist.tracks[currentTrackId].title);

            $playerInterface.find('li.track:not(".track-'+currentTrackId+'")').removeClass('playing');
            $playerInterface.find('li.track:not(".track-'+currentTrackId+'")').removeClass('selected');

            $playerInterface.find('div.ps-album-art').html($$('img', {'src': playlist.tracks[currentTrackId].art}));
        }

        var playCurrentTrack = function() {
            $playerInstance.jPlayer("play");
        }

        var pauseCurrentTrack = function () {
            $playerInstance.jPlayer("pause");
        }

        var onPauseCurrentTrack = function () {
            $currentTrack.removeClass('playing');
        }

        var onSelectTrack = function (e) {
            e.preventDefault();
            e.stopPropagation();

            var newTrackId = $(this).parent().attr('class').match(/track-([0-9]+)/)[1];


            if(newTrackId == currentTrackId) {
                if(playing) {
                    pauseCurrentTrack();
                }
                else {
                    playCurrentTrack();
                }

            }
            else {
                setCurrentTrack(newTrackId);
                playCurrentTrack();
            }
        }

        var previousTrack = function () {
            var index = (currentTrackId - 1 >= 0) ? currentTrackId - 1 : playlist.tracks.length - 1;

            setCurrentTrack(index);

            if(playing) {
                playCurrentTrack();
            }
        }

        var nextTrack = function () {
            var index = (currentTrackId + 1 < playlist.tracks.length) ? currentTrackId + 1 : 0;

            setCurrentTrack(index);

            if(playing) {
                playCurrentTrack();
            }
        }

        var onClickExtra = function(e) {
            e.preventDefault();
            e.stopPropagation();

            console.log('extra');
        }

        var setupListeners = function () {
            $playerInstance.bind($.jPlayer.event.play, function(event) {
                if(!$currentTrack.hasClass('playing')) {
                    $currentTrack.addClass('playing');
                }
                $currentTrack.addClass('playing');
                playing = true;
            });

            $playerInstance.bind($.jPlayer.event.progress, function(event) {
                // show loading animation?
                playing = true;
            });

            $playerInstance.bind($.jPlayer.event.pause, function(event) {
                onPauseCurrentTrack();
                playing = false;
            });

            $playerInstance.bind($.jPlayer.event.ended, function(event) {
                playing = true;
                nextTrack();
            });

            // handle autoPlay option
            setCurrentTrack(current);
            if (options.autoPlay) {
                playCurrentTrack();
            }
        }

        construct();
    }
})(jQuery);
