/**
Yahoo Media Player - TrackSeek extension

Displays a visual position indicator and allows the user to control the seek position

@author: Eric Fehrenbacher
@company: Yahoo!
@version 0.1.2
*/
var TrackSeek = function() {

    // reference to YMP
    this.player = YAHOO.MediaPlayer;

    // position of the left edge of the slider relative to the page
    this.seekControlX = 0;

    // reference to the currently playing track
    this.track = null;

    // the elapsed time of the currently playing track
    this.elapsed = 0;

    // the duration of the currently playing track
    this.duration = 0;

    // tells us if the track is playing or not
    this.paused = true;

    // tells us if we are dragging the slider or not
    this.dragging = false;

    // tracks the percentage of movement from the left edge of the control
    this.position = 0;

    // setup of delegates, subscribers, and UI
    this.init();

};
TrackSeek.create = function(args) {
    YAHOO.mediaplayer.TrackSeek = new TrackSeek(args[0]);
    return YAHOO.mediaplayer.TrackSeek;
};
TrackSeek.attachElement = 'ymp-meta-album-title';
TrackSeek.prototype = {

    /**
    Fires during the contruction of this object
    @method init
    */
    init: function() {

        // 
        this.setupUI();

        // some ui specs
        this.ui = {
            // define the total width
            width: function() {
                return parseInt(YAHOO.ympyui.util.Dom.getStyle('ymp-seek', 'width'));
            },
            // define the left edge
            left: function() {
                return Math.round(parseInt(YAHOO.ympyui.util.Dom.getStyle('ymp-seek-thumb', 'width')) / 2);
            },
            // define the right edge
            right: function() {
                return this.width() - this.left();
            }
        };

        // initialize default seek position...
        this.onPositionChange(1);

        // handle mousedown on the position control
        YAHOO.ympyui.util.Event.on('ymp-seek', 'mousedown', this.seekStartDrag, this, true);

        // handle clicks on the position control
        YAHOO.ympyui.util.Event.on('ymp-seek', 'click', this.stopEvent);

        // track hash of active track when play is clicked
        this.player.onTrackStart.subscribe(this.onPlay, this, true);

        // update position based on elapsed time of active track
        this.player.onProgress.subscribe(this.onProgress, this, true);

        //
        this.player.onTrackPause.subscribe(this.onPause, this, true);

        // 
        YAHOO.ympyui.util.Event.addListener(['ymp-next', 'ymp-prev'], 'click', function() {
            this.onPositionChange(1);
        }, this, true);

    },

    /**
    We just setup the GUI here.
    @method setupUI
    */
    setupUI: function() {

        // grab the volume control
        var displaced = document.getElementById(TrackSeek.attachElement);
        YAHOO.ympyui.util.Dom.setStyles(displaced, { display: 'none' });

        // create slider
        var seekContainer = document.createElement('div');
        seekContainer.id = 'ymp-seek';
        YAHOO.ympyui.util.Dom.setStyles(seekContainer, {
            position: 'absolute',
            width: '190px',
            height: '15px',
            zIndex: '2'
        });
        displaced.parentNode.insertBefore(seekContainer, displaced);
        /*
        // we need to be notified when the timer changes size so we can readjust
        // or better yet, why do we need to readjust the timer should be doing that
        var seekRegion = YAHOO.ympyui.util.Dom.getRegion(seekContainer);
        var seekWidth = seekRegion.right - seekRegion.left;
        YAHOO.ympyui.util.Dom.setStyle(seekContainer, 'width', (seekWidth - 10) + 'px');
        */

        var seekCover = document.createElement('div');
        seekCover.id = 'ymp-seek-cover';
        YAHOO.ympyui.util.Dom.setStyles(seekCover, {
            display: 'block',
            position: 'absolute',
            overflow: 'hidden',
            top: '5px',
            left: '0px',
            width: '100%',
            height: '4px',
            backgroundColor: '#D6D6D6'
        });
        seekContainer.appendChild(seekCover);

        var seekCoverElapsed = document.createElement('div');
        seekCoverElapsed.id = 'ymp-seek-cover-elapsed';
        YAHOO.ympyui.util.Dom.setStyles(seekCoverElapsed, {
            display: 'block',
            position: 'absolute',
            visibility: 'hidden',
            overflow: 'hidden',
            top: '0px',
            left: '0px',
            width: '100%',
            height: '4px',
            backgroundColor: '#929392'
        });
        seekCover.appendChild(seekCoverElapsed);
        YAHOO.ympyui.util.Event.addListener(seekContainer, 'mouseover', function() {
            this.style.backgroundColor = '#CEFD0D';
        }, seekCoverElapsed, true);
        YAHOO.ympyui.util.Event.addListener(seekContainer, 'mouseout', function() {
            this.style.backgroundColor = '#929392';
        }, seekCoverElapsed, true);

        var seekThumb = document.createElement('div');
        seekThumb.id = 'ymp-seek-thumb';
        YAHOO.ympyui.util.Event.addListener(seekThumb, 'mouseover', function() {
            this.style.borderColor = '#CEFD0D';
        }, seekThumb, true);
        YAHOO.ympyui.util.Event.addListener(seekThumb, 'mouseout', function() {
            this.style.borderColor = '#DDDDDD #B2B2B2 #B2B2B2 #DDDDDD';
        }, seekThumb, true);
        YAHOO.ympyui.util.Dom.setStyles(seekThumb, {
            display: 'block',
            position: 'absolute',
            overflow: 'hidden',
            top: '3px',
            left: '0px',
            width: '4px',
            height: '7px',
            cursor: 'pointer',
            backgroundColor: '#E9E8E8',
            borderWidth: '1px',
            borderStyle: 'solid',
            borderColor: '#DDDDDD #B2B2B2 #B2B2B2 #DDDDDD'
        });
        seekContainer.appendChild(seekThumb);

    },

    /**
    Provides a shortcut for stopping an event
    @method stopEvent
    @param {DOMEvent} evt
    */
    stopEvent: function(evt) {
        YAHOO.ympyui.util.Event.stopEvent(evt);
    },

    /**
    Event handler for when the user starts to drag the position slider
    @method seekStartDrag
    @param {Object} eventObj The HTML event object.
    */
    seekStartDrag: function(evt) {
        if (this.paused) {
            return;
        }

        this.stopEvent(evt);
        this.dragging = true;

        // get the current position of the left edge of the slider relative to the page
        this.seekControlX = YAHOO.ympyui.util.Dom.getX('ymp-seek');

        // notify everyone about position change
        this.notifySeekChange(evt);

        YAHOO.ympyui.util.Event.on(document, 'mousemove', this.notifySeekChange, this, true);
        YAHOO.ympyui.util.Event.on(document, 'mouseup', this.seekMouseUp, this, true);
    },

    /**
    Event handler when the user releases the mouse after dragging the position slider. Remove the appropriate event listeners.
    @method seekMouseUp
    @param {Object} eventObj The HTML event object
    */
    seekMouseUp: function(evt) {
        this.dragging = false;
        this.stopEvent(evt);
        this.elapsed = this.duration - (this.position * this.duration);

        YAHOO.ympyui.util.Event.removeListener(document, 'mousemove', this.notifySeekChange);
        YAHOO.ympyui.util.Event.removeListener(document, 'mouseup', this.seekMouseUp);

        if (this.paused) {

            this.player.pause();
            return;

            // reduce the volume before we play so that no one here's the brief noise
            var volume = this.player.getVolume();
            this.player.setVolume(0);
            this.player.play(this.track, this.elapsed);
            /*
            it would be nice to be able to move the position while paused, but...
            for some reason this hack won't work here, haven't figured out why yet
            */
            /*
            this.playCheck = YAHOO.ympyui.lang.later(100, this, function(volume) {
            if (this.player.getPlayerState() == 2) {
            this.playCheck.cancel();
            //this.updateSeekPosition();
            this.onProgress({elapsed: this.elapsed, duration: this.duration})
            console.log("asddddddddd");
            this.player.pause();
            //this.player.setVolume(volume);
            }
            }, [volume], true);
            */
        } else {
            this.player.play(this.track, this.elapsed);
        }

    },

    /**
    Get the right requested position based on where the user has dragged the position slider and then fire the position change request event for that position
    @method notifySeekChange
    @param {DOMEvent} evt
    */
    notifySeekChange: function(evt) {
        this.stopEvent(evt);
        var newMouseX = YAHOO.ympyui.util.Event.getPageX(evt);
        var xDiff = (newMouseX - this.seekControlX);
        xDiff -= 0;
        var thumbLeft;

        // calculate position percentage (0 - 1) and fire the event to notify whoever is listening
        if ((xDiff >= this.ui.left()) && (xDiff < this.ui.right())) {
            // mouse is within the constraint
            thumbLeft = xDiff - this.ui.left();
        } else if (xDiff >= this.ui.right()) {
            // mouse is way below the position, so cap the thumb at the maximum x it is allowed to go
            thumbLeft = this.ui.right() - this.ui.left();
        } else if (xDiff < this.ui.left()) {
            // mouse is way above the position, so cap the x at 0
            thumbLeft = 0;
        }

        // percentage of movement from the left edge of the control
        this.position = 1 - (thumbLeft / (this.ui.right() - this.ui.left()));

        this.onPositionChange(this.position);
    },

    /**
    Event handler for onPlay. Record the track as a mediaObject for reference.
    @method onPlay
    @param {Object} track The currently playing track
    */
    onPlay: function(track) {
        this.paused = false;
        this.track = track.mediaObject;
    },

    /**
    This function updates the seek position based on the elapsed time of the currently playing track
    @method onProgress
    @param {Object} options
    */
    onProgress: function(options) {
        this.elapsed = options.elapsed;
        this.duration = options.duration || (YAHOO.mediaplayer.TrackResume && YAHOO.mediaplayer.TrackResume.duration) || 0;
       // this.duration = YAHOO.mediaplayer.getTrackDuration();
        if (!this.dragging && (this.duration != 0)) {
            var thumbLeft;

            // convert thumb position into seek position
            var xDiff = Math.ceil((Math.ceil(this.elapsed) * this.ui.right() - this.ui.left()) / Math.ceil(this.duration));
            xDiff -= 0;

            // calculate position percentage (0 - 1) and fire the event to notify whoever is listening
            if ((xDiff >= this.ui.left()) && (xDiff < this.ui.right())) {
                // seek is within the constraint
                thumbLeft = xDiff - this.ui.left();
            } else if (xDiff >= this.ui.right()) {
                // seek is way below the position, so cap the thumb at the maximum x it is allowed to go
                thumbLeft = this.ui.right() - this.ui.left();
            } else if (xDiff < this.ui.left()) {
                // seek is way above the position, so cap the x at 0
                thumbLeft = 0;
            }

            // percentage of seek position from the left edge of the controle
            var position = 1 - (thumbLeft / (this.ui.right() - this.ui.left()));

            this.onPositionChange(position);
        }
    },

    /**
    Event handler for onPlay. Record the track as a mediaObject for reference.
    @method onPause
    @param {Object} track The currently playing track
    */
    onPause: function(track) {
        this.paused = true;
    },

    /**
    Event handler for onPositionChange. If the seek position is changed through API update the view appropriately
    @method onPositionChange
    @param {Object} seek The new position [0-1]
    */
    onPositionChange: function(position) {

        // convert seek position into thumb position
        var thumbLeft = (1 - position) * (this.ui.right() - this.ui.left());

        // adjust seek thumb position
        YAHOO.ympyui.util.Dom.setStyle('ymp-seek-thumb', 'left', thumbLeft + 'px');

        // adjust elapsed position
        YAHOO.ympyui.util.Dom.setStyle('ymp-seek-cover-elapsed', 'visibility', 'visible');
        YAHOO.ympyui.util.Dom.setStyle('ymp-seek-cover-elapsed', 'left', -((this.ui.right() - this.ui.left()) - thumbLeft) + 'px');

    }

};

/**
This creates a new TrackSeek object and attaches to the MediaPlayer
*/
(typeof YAHOO != 'undefined') && YAHOO.ympyui.util.Event.onAvailable(TrackSeek.attachElement, TrackSeek.create, TrackSeek);
