// ---------- Popup ----------

RHG.Classes.AudioPlayer = new RHG.Class();
RHG.Classes.AudioPlayer.selectors = {
};

RHG.Classes.AudioPlayer.classFunction = function(configObject) {
    var classFunctionPub = {};
    var thisClass = RHG.Classes.AudioPlayer;
    var selectors = thisClass.selectors;
    var targetJq;
    var currentSound;

    var currentState = null;
    var statePlaying = "PLAY";
    var statePaused = "PAUSE";
    var stateStopped = "STOP";

    var currentVolume = 0.5;
    var volumeIncrement = 0.1;

    var soundManagerReady = function() { };

    if (!window.soundManager) {
        window.soundManager = new SoundManager();

        soundManager.url = '/content/swf/soundmanager2.swf';
        soundManager.useFlashBlock = false; // optionally, enable when you're ready to dive in
        soundManager.debugMode = false;

        jQuery(document).ready(function() {
            soundManager.beginDelayedInit();
        })
    }


    // <section class="audio-interface">
    // 	<h2 class="rm">Audio Player</h2>
    // 	<h3><strong>Now Playing:</strong> <span class="audio-title">Audiobook sound clip<span></h3>
    // 	
    // 	<section class="audio-progress">
    // 		<h4 class="rm">Progress:</h4>
    // 		<div class="audio-slider">
    //			<div class="progress-bar">
    //				<div class="progress-bar-loaded"></div>
    //				<div class="progress-bar-played"></div>
    // 				<div class="progress-bar-marker"></div>
    // 			</div>
    // 		</div>
    // 		<p>0:13/9:30</p>
    // 	</section>
    // 	
    // 	<ul class="audio-controls">
    // 		<li class="audio-play"><a href="#">Pause</a></li>
    // 		<li class="audio-mute-off"><a href="#">Mute</a></li>
    // 		<li class="audio-volup"><span>Volume Up</span></li>
    // 		<li class="audio-voldown"><a href="#">Volume Down</a></li>
    // 	</ul>
    // </section>

    var ProgressBar = function() {
        var ProgressBarPub = new Object();

        function pageOffset(elem) {
            var offset = new Object;
            offset.x = 0;
            offset.y = 0;

            // Add up the offsets from this element to the document body
            while (elem.nodeName != 'BODY') {
                offset.x += elem.offsetLeft;
                offset.y += elem.offsetTop;
                elem = elem.offsetParent;
            }

            return offset;
        }

        // Setup HTML elements
        var jqBar = jQuery('<div class="progress-bar disabled" />');
        var jqLoaded = jQuery('<div class="progress-bar-loaded" />');
        var jqPlayed = jQuery('<div class="progress-bar-played" />');
        var jqMarker = jQuery('<div class="progress-bar-marker" />');


        jqBar.append(jqLoaded, jqPlayed, jqMarker);


        /* ========== CLASSES ========== */

        /* ---------- MovableMarker ----------
        jqMarker:	(required) [jQuery object]  marker element
        jqBar:		(required) [jQuery object]  bar element
        keepInside:	(optional: true) [true / false]  Keep the marker inside the bar (compensates for marker width)
        alignPoint:	(optional: 0.5) [0 - 1]  How to align the marker, 0 = left, 1 = right, 0.75 = slighty to the right, etc
        */
        function MovableMarker(jqMarker, jqBar, keepInside, alignPoint) {
            var MovableMarkerPub = new Object();

            var keepInside = (keepInside != undefined) ? keepInside : true;
            var alignPoint = (typeof (alignPoint) == 'number') ? alignPoint : 0.5;
            var isBeingDragged = false;

            MovableMarkerPub.repositionFunction = function() { };
            MovableMarkerPub.moveFunction = function() { };
            MovableMarkerPub.currentAmmount = 0;
            MovableMarkerPub.boundries = { "start": 0, "end": 1 };
            var mouseBoundingBoxMargin = 150;
            var startAmmount = 0;
            MovableMarkerPub.enabled = false;

            function setMarkerPosition(ammount) {
                jqMarker.css("left", (ammount * 100) + "%");
                // Compensate for marker width
                if (keepInside) {
                    jqMarker.css("margin-left", -(jqMarker[0].offsetWidth * ammount) + "px");
                } else {
                    jqMarker.css("margin-left", -(jqMarker[0].offsetWidth * alignPoint) + "px");
                }

                MovableMarkerPub.moveFunction(ammount);
                MovableMarkerPub.currentAmmount = ammount;
            }

            function beginMarkerDrag(evt) {
                if (MovableMarkerPub.enabled) {
                    startAmmount = MovableMarkerPub.currentAmmount;
                    var mouseOffsetMarkerX = evt.pageX - pageOffset(jqMarker[0]).x;

                    // Stop IE Draggable/Selectable
                    document.body.ondrag = function() { return false; };
                    document.body.onselectstart = function() { return false; };

                    isBeingDragged = true;

                    function stopMarkerDrag(evt) {
                        jQuery(document).unbind("mousemove", positionMarker);
                        jQuery(document).unbind("mouseup", stopMarkerDrag);
                        jQuery(document).unbind("mouseout", leftHTML);

                        // Reset IE Draggable/Selectable
                        document.body.ondrag = function() { };
                        document.body.onselectstart = function() { };

                        isBeingDragged = false;

                        // Fire reposition Event
                        MovableMarkerPub.repositionFunction(MovableMarkerPub.currentAmmount);
                    }

                    function resetMarker(evt) {
                        setMarkerPosition(startAmmount)
                    }

                    function positionMarker(evt) {

                        var xOffset = evt.pageX - pageOffset(jqBar[0]).x;
                        var yOffset = evt.pageY - pageOffset(jqBar[0]).y;

                        var barWidth = jqBar[0].clientWidth;
                        var barHeight = jqBar[0].clientHeight;

                        var markerPosition = xOffset / barWidth;
                        var mouseCompensation = mouseOffsetMarkerX / barWidth;
                        markerPosition -= mouseCompensation;

                        var ammountMarker = 0;

                        if (keepInside) {
                            // Marker width compensation
                            ammountMarker = (jqMarker[0].offsetWidth * markerPosition) / jqBar[0].clientWidth;
                        } else {
                            ammountMarker = (jqMarker[0].offsetWidth * alignPoint) / jqBar[0].clientWidth;
                        }
                        markerPosition += ammountMarker;

                        if (markerPosition < MovableMarkerPub.boundries.start) {
                            setMarkerPosition(MovableMarkerPub.boundries.start);
                        } else if (markerPosition > MovableMarkerPub.boundries.end) {
                            setMarkerPosition(MovableMarkerPub.boundries.end);
                        } else {
                            setMarkerPosition(markerPosition);
                        }

                        // Reset the marker position if the mouse moves outside of the bounding box
                        if (xOffset < -mouseBoundingBoxMargin) {
                            resetMarker(evt);
                        }
                        if (xOffset - barWidth > mouseBoundingBoxMargin) {
                            resetMarker(evt);
                        }
                        if (yOffset < -mouseBoundingBoxMargin) {
                            resetMarker(evt);
                        }
                        if (yOffset - barHeight > mouseBoundingBoxMargin) {
                            resetMarker(evt);
                        }
                    }

                    function leftHTML(evt) {
                        // Get the element the mouse moved to (mouseover)
                        var movedTo = (evt.relatedTarget) ? evt.relatedTarget : evt.toElement;

                        if (!movedTo || movedTo.nodeName == "HTML") {
                            // Mouse moved out of document (no movedTo)
                            resetMarker(evt)
                            stopMarkerDrag(evt);
                        }
                    }

                    jQuery(document).bind("mouseup", stopMarkerDrag);
                    jQuery(document).bind("mousemove", positionMarker);
                    jQuery(document).bind("mouseout", leftHTML); // Ideally we wouldn't do this, but we can't detect mouseups outside the document (i.e. people would get a 'stuck' mouse button)

                }

                // Stop other onmousedown events
                return false;
            }

            // Marker movement
            jqMarker.bind("mousedown", beginMarkerDrag);

            setMarkerPosition(0);

            // Return
            MovableMarkerPub.setPosition = function(pos) {
                if (!isBeingDragged) {
                    setMarkerPosition(pos);
                }
            }

            MovableMarkerPub.enable = function() {
                MovableMarkerPub.enabled = true;
            }
            MovableMarkerPub.disable = function() {
                MovableMarkerPub.enabled = false;
            }

            return MovableMarkerPub;
        }




        /* ========== FUNCTIONS ========== */

        // PRIVATE



        // PUBLIC

        ProgressBarPub.setPlayed = function(ammount) {
            jqPlayed.css("width", (ammount * 100) + "%");
            positionMarker.setPosition(ammount);
        }

        ProgressBarPub.setLoaded = function(ammount) {
            jqLoaded.css("width", (ammount * 100) + "%")
        }


        ProgressBarPub.enable = function() {
            jqBar.removeClass("disabled");
            positionMarker.enable();
        }

        ProgressBarPub.disable = function() {
            jqBar.addClass("disabled");
            positionMarker.disable();
        }


        /* ========== SETUP ========== */

        // Create position marker
        var positionMarker = new MovableMarker(jqMarker, jqBar, false);
        ProgressBarPub.positionListener = function() { };
        positionMarker.repositionFunction = function(evt) {
            ProgressBarPub.positionListener(evt);
        }

        // Jump to point on position marker
        jqBar.bind("mousedown", function(evt) {
            if (positionMarker.enabled) {
                var xOffset = evt.pageX - pageOffset(jqBar[0]).x;
                positionMarker.setPosition(xOffset / jqBar[0].clientWidth);

                // Fire reposition Event
                positionMarker.repositionFunction(positionMarker.currentAmmount);
            }
        });

        ProgressBarPub.element = jqBar[0];

        // Return
        return ProgressBarPub;
    }

    var interfaceJq = jQuery('<div class="audio-interface"><h2 class="rm">Audio Player</h2></div>');

    var infoJq = jQuery('<h3></h3>');
    var statusJq = jQuery('<strong></strong>');
    var titleJq = jQuery('<span class="audio-title"></span>');
    infoJq.append(statusJq).append(titleJq);

    var progressJq = jQuery('<div class="audio-progress"><h4 class="rm">Progress:</h4></div>');
    var sliderJq = jQuery('<div class="audio-slider"></div>');
    var timeJq = jQuery("<p></p>");

    var progBar = new ProgressBar();
    sliderJq.append(progBar.element);
    progBar.setLoaded(0);
    progBar.setPlayed(0);


    progressJq.append(sliderJq).append(timeJq);

    var controlsJq = jQuery('<ul class="audio-controls"></ul>');

    playControlButton = new RHG.Utilities.ControlButton("Play", "audio-play", null, "li");
    pauseControlButton = new RHG.Utilities.ControlButton("Pause", "audio-pause", null, "li");
    playpauseToggleButton = new RHG.Utilities.ToggleButton([playControlButton, pauseControlButton])
    pauseControlButton.setActionFunction(function() {
        pause();
    });
    playControlButton.setActionFunction(function() {
        play();
    });

    muteOnControlButton = new RHG.Utilities.ControlButton("Mute", "audio-mute-on", null, "li");
    muteOffControlButton = new RHG.Utilities.ControlButton("Un-Mute", "audio-mute-off", null, "li");
    muteToggleButton = new RHG.Utilities.ToggleButton([muteOnControlButton, muteOffControlButton])
    muteOnControlButton.setActionFunction(function() {
        mute();
    });
    muteOffControlButton.setActionFunction(function() {
        unmute();
    });

    volUpControlButton = new RHG.Utilities.ControlButton("Increase Volume", "audio-volup", function() {
        volup();
    }, "li");
    volDownControlButton = new RHG.Utilities.ControlButton("Decrease Volume", "audio-voldown", function() {
        voldown();
    }, "li");

    controlsJq.append(playpauseToggleButton.currentControlButton.elemJq).append(muteToggleButton.currentControlButton.elemJq).append(volUpControlButton.elemJq).append(volDownControlButton.elemJq);

    interfaceJq.append(infoJq).append(progressJq).append(controlsJq);

    var buildInterface = function() {
        targetJq.after(interfaceJq);
    }

    var initPlayer = function(url, title) {
        targetJq.remove();

        if (typeof (currentSound) == "object") {
            currentSound.destruct();
        }

        currentSound = soundManager.createSound({
            id: 'mySound',
            url: url,
            // optional sound parameters here, see Sound Properties for full list
            volume: 50,
            autoPlay: false,
            onplay: eventWaiting,
            onresume: eventPlaying,
            onpause: eventPaused,
            onstop: eventStopped,
            whileplaying: eventPlaying,
            whileloading: eventLoading,
            onfinish: eventStopped
        });

        currentState = stateStopped;

        playpauseToggleButton.setState(0);
        playControlButton.enable();
        muteToggleButton.setState(0);

        timeJq.text("00:00/00:00");

        progBar.enable();
        progBar.setPlayed(0);
        progBar.positionListener = function(evt) {
            var duration = currentSound.durationEstimate;
            if (currentSound.readyState == 3) {
                duration = currentSound.duration;
            }
            progBar.setPlayed(currentSound.position / duration);

            currentSound.play();
            currentSound.setPosition(duration * evt);
        }

        titleJq.text(title);

        muteToggleButton.setState(muteOnControlButton);
        muteOnControlButton.enable();
        volEnableDisable();
    }

    var milliToMins = function(milliseconds) {
        var d = new Date(milliseconds);
        var mins = d.getMinutes().toString();
        var secs = d.getSeconds().toString();

        if (mins.length == 1) {
            mins = "0" + mins;
        }
        if (secs.length == 1) {
            secs = "0" + secs;
        }

        return mins + ":" + secs;
    }

    var eventPlaying = function() {
        playpauseToggleButton.setState(1);
        pauseControlButton.enable();
        currentState = statePlaying;
        statusJq.text("Playing:");

        timeJq.text(milliToMins(currentSound.position) + "/" + milliToMins(currentSound.duration));

        var duration = currentSound.durationEstimate;
        if (currentSound.readyState == 3) {
            duration = currentSound.duration;
        }

        progBar.setPlayed(currentSound.position / duration);        
    }
    var eventPaused = function() {
        playpauseToggleButton.setState(0);
        playControlButton.enable();
        currentState = statePaused;
        statusJq.text("Paused:")
    }
    var eventStopped = function() {
        currentState = stateStopped;
        statusJq.text("Stopped:")
    }
    var eventWaiting = function() {
        statusJq.text("Loading:");
    }
    var eventLoading = function() {
        progBar.setLoaded(currentSound.bytesLoaded / currentSound.bytesTotal)
    }
    var eventStopped = function() {
        statusJq.text("Stopped:");
    }

    var play = function() {
        if (typeof (currentSound) == "object") {
            if (currentState == statePaused) {
                currentSound.resume();
            } else {
                currentSound.play();
            }
        }        
        configObject.onInteraction("Play");
    }

    var pause = function() {
        if (typeof (currentSound) == "object") {
            currentSound.pause();
        }
        configObject.onInteraction("Pause");
    }

    var mute = function() {
        if (typeof (currentSound) == "object") {
            currentSound.mute();

            muteToggleButton.setState(muteOffControlButton);
            muteOffControlButton.enable();
        }
        configObject.onInteraction("Mute");
    }

    var unmute = function() {
        if (typeof (currentSound) == "object") {
            currentSound.unmute();

            muteToggleButton.setState(muteOnControlButton);
            muteOnControlButton.enable();
        }
        configObject.onInteraction("Unmute");
    }

    var volEnableDisable = function() {
        if (currentVolume == 1) {
            volUpControlButton.disable();
        } else {
            volUpControlButton.enable();
        }
        if (currentVolume == 0) {
            volDownControlButton.disable();
        } else {
            volDownControlButton.enable();
        }
    }

    var volup = function() {
        currentVolume += volumeIncrement;
        if (currentVolume > 1) {
            currentVolume = 1;
        }
        if (typeof (currentSound) == "object") {
            currentSound.setVolume(currentVolume * 100);
        }
        volEnableDisable();
        configObject.onInteraction("Vol Up");
    }

    var voldown = function() {
        currentVolume -= volumeIncrement;
        if (currentVolume < 0) {
            currentVolume = 0;
        }
        if (typeof (currentSound) == "object") {
            currentSound.setVolume(currentVolume * 100);
        }
        volEnableDisable();
        configObject.onInteraction("Vol Down");
    }


    // 36:54

    classFunctionPub.init = function() {
        if (configObject.uniqueTargetNodeOrSelector) {
            targetJq = jQuery(configObject.uniqueTargetNodeOrSelector)
            var audioUrl = targetJq.attr('href');
            var audioTitle = targetJq.text();

            soundManager.onready(function() {
                buildInterface();
                initPlayer(audioUrl, audioTitle)
            });
        }
    }

    return classFunctionPub;
}
