<?xml version="1.0"?>
<!-- TimedTextApp.mxml -->
<mx:Application 
    xmlns:mx="http://www.adobe.com/2006/mxml" 
    xmlns:accessibility="flash.accessibility.*"
    xmlns:controls="com.modernista.mx.controls.*"
    xmlns:videoClasses="com.modernista.mx.controls.videoClasses.*" 
    viewSourceURL="srcview/index.html" 
    applicationComplete="init()" 
    width="100%" 
    height="100%" 
    layout="absolute" 
    autoLayout="true" 
    backgroundGradientColors="[0,0]" 
    focusIn="handleFocusIn(FocusEvent(event))" 
    focusOut="handleFocusOut(FocusEvent(event))">
    
    <mx:Script>
        <![CDATA[
        import com.modernista.mx.controls.videoClasses.CaptionChangeEvent;
        import com.modernista.mx.controls.videoClasses.CaptionTargetEvent;
        import com.modernista.mx.controls.videoClasses.VideoDisplayCaptioning;
        import com.modernista.swffocus.SWFFocus;
        
        import flash.display.StageDisplayState;
        import flash.events.TimerEvent;
        import flash.utils.Timer;
        
        import mx.core.mx_internal;
        import mx.events.VideoEvent;
        
        use namespace mx_internal;
        
        // seeking
        private var _seekBarScrubTolerance:Number;
        private var _seekBarTimer:Timer;
        private var _lastScrubPos:Number;
        private var _playAfterScrub:Boolean;
        
        public static const SEEK_BAR_INTERVAL_DEFAULT:Number = 250;
        public static const SEEK_BAR_SCRUB_TOLERANCE_DEFAULT:Number = 5;
        
        public var textStrokeFilter:GlowFilter = new GlowFilter(0,0.5,2,2,10,2);
        public var dispState:String; 
        
           
        private var _videoSource:String =  "assets/flv/This-Is-Not-a-Photograph.flv"
        public function get videoSource():String {
            return _videoSource;
        }
        public function set videoSource(p_videoSource:String):void {
            if(p_videoSource == _videoSource){
                return;
            }
            _videoSource = p_videoSource;
            
            if(videoDisplay){
                videoDisplay.source = _videoSource;
            }
        }
        
        private var _captionsSource:String = "assets/flv/This-Is-Not-a-Photograph.xml"
        public function get captionsSource():String {
            return _captionsSource;
        }
        public function set captionsSource(p_captionsSource:String):void {
            if(p_captionsSource == _captionsSource){
                return;
            }
            _captionsSource = p_captionsSource;
            videoDisplayCaptioning.source = _captionsSource;
        }
        
        private function init():void {
            SWFFocus.init(Application.application.stage as Stage);
            Application.application.stage.addEventListener(Event.RESIZE, resizeHandler, false, 0, true);
            videoDisplayCaptioning.addEventListener(CaptionTargetEvent.CAPTION_TARGET_CREATED, captionTargetCreatedHandler, false, 0, true);             
             /* Set up full screen handler. */
            Application.application.stage.addEventListener(FullScreenEvent.FULL_SCREEN, fullScreenHandler);
            dispState = Application.application.stage.displayState;   
            
            
            _seekBarScrubTolerance = SEEK_BAR_SCRUB_TOLERANCE_DEFAULT;
        
            // setup timers
            _seekBarTimer = new Timer(SEEK_BAR_INTERVAL_DEFAULT);
            _seekBarTimer.addEventListener(flash.events.TimerEvent.TIMER, seekBarListener);
            
            var flashvars:Object = Application.application.loaderInfo.parameters;
            
            for(var i:String in flashvars){
                var key:String = i;
                var value:* = flashvars[key];
                
                switch(key.toLowerCase()){
                    case "source" :
                    case "videosource" :
                    case "s1" :
                        videoSource = value;
                        continue;
                        break;
                    case "captionssource" :
                    case "timedtext" :
                    case "s7" :
                        captionsSource = value;
                        continue;
                        break;
                    case "s2" :
                        videoDisplay.autoPlay = Boolean(value == "playing");
                        if(videoDisplay.source != "" 
                           && !Accessibility.active){
                            videoDisplay.play();
                            
                        }
                        continue;
                        break;
                }
                
                if(videoDisplay.hasOwnProperty(key)){
                    if(value == "true" || value == "false"){
                        value = Boolean(value);
                    }
                    if(!isNaN(parseFloat(value))){
                        value = parseFloat(value);
                    }
                    videoDisplay[key] = value;
                    if(key == "autoPlay" && value==true){
                        if(videoDisplay.source != "" 
                           && !Accessibility.active){
                            videoDisplay.play();
                        }
                    }
                }
            } 
            
            if(videoDisplay.source != _videoSource){
                videoDisplay.close();
                videoDisplay.source = _videoSource;
                videoDisplay.load();
            }
            if(videoDisplayCaptioning.source != _captionsSource){
                videoDisplayCaptioning.source = _captionsSource;
            }
            showControls();   
        }
        
        private function captionTargetCreatedHandler(event:CaptionTargetEvent):void {
            
            var captionTarget:DisplayObject = VideoDisplayCaptioning(event.target).captionTarget;
            if(captionTarget is TextField){
                videoDisplayCaptioning.autoLayout = false;
                
                var captionTargetWrapper:Sprite =  new Sprite();
                
                captionTarget.parent.addChild(captionTargetWrapper);
                captionTargetWrapper.addChild(captionTarget);
                captionTarget.visible = videoDisplayCaptioning.showCaptions;
                captionTarget.x = 5;
                captionTarget.y = videoDisplay.videoHeight-5-captionTarget.height;
                captionTarget.width = videoDisplay.videoWidth - 10;
                
                
                TextField(captionTarget).background = false;
                TextField(captionTarget).selectable = false;
                TextField(captionTarget).gridFitType = GridFitType.PIXEL;
                TextField(captionTarget).antiAliasType = AntiAliasType.ADVANCED;
                TextField(captionTarget).embedFonts = true;
            
                var gf:GlowFilter = new GlowFilter(0,1,2,2,10,3); 
                var dsf:DropShadowFilter = new DropShadowFilter(1,90,0,0.5,4,4,1);
                
                
                captionTarget.filters = [textStrokeFilter, dsf];
            }
        }
        
        private function playPauseClickHandler(event:MouseEvent = null):void{
            if(videoDisplay.playing){
                videoDisplay.pause();
                playPauseButton.selected = false;
            } else if(!videoDisplay.playing){
                videoDisplay.play();
                playPauseButton.selected = true;
            }
        }
        
        private function stopClickHandler(event:MouseEvent = null):void{
            videoDisplay.stop();
            playheadUpdateHandler();
            playPauseButton.selected = false;
            showControls();
        }
        
        
        private function videoTimeConvert(myTime:Number):String{
             var date:Date = new Date(myTime*1000);
            
            return (myTime>3600) ? this.dateFormatterHours.format(date) : this.dateFormatter.format(date);
        }
        
        private var _isPlaying:Boolean = false;
        
        private function seekBar_thumbPress():void {
            
            videoDisplay.removeEventListener(VideoEvent.PLAYHEAD_UPDATE, playheadUpdateHandler);
            
            if (videoDisplay.playing) {
                _playAfterScrub = true;
            }
                
            _seekBarTimer.start();
            videoDisplay.pause();
            
            this.videoDisplayCaptioning.removeOldCaptions(NaN);
            if(this.videoDisplayCaptioning.showCaptions){
                this.videoDisplayCaptioning.displayCaptionNow();
                adjustCaptionTargetPosition();
            }
        }
        
        private function seekBar_thumbRelease():void {
            
            seekBarListener(null);
            
            if(_playAfterScrub){
                videoDisplay.play();
                _playAfterScrub = false;
            }
            
            videoDisplayCaptioning.removeOldCaptions(NaN);
            if(videoDisplayCaptioning.showCaptions){
                videoDisplayCaptioning.displayCaptionNow();
                adjustCaptionTargetPosition();
            }
        }
        
        private function playheadUpdateHandler(event:VideoEvent=null):void {
           
            if ( !isNaN(videoDisplay.totalTime) &&
             (videoDisplay.state != "seeking") ) {
                event = VideoEvent(event);
                seekBar.value=videoDisplay.playheadTime;
            }
            
            stopButton.enabled = (videoDisplay.playheadTime>0);
            
            adjustCaptionTargetPosition();
        }
        
        private function rewindHandler(e:VideoEvent=null):void {
            stopClickHandler();
        }
           
        private function captionChangeHandler(e:CaptionChangeEvent=null):void {
            adjustCaptionTargetPosition();
        }
        
        
        private function resizeHandler(e:Event=null):void {
            videoControls.percentWidth=100;
            videoControls.setConstraintValue("bottom",0);
            adjustCaptionTargetPosition();
        }
           
        private function adjustCaptionTargetPosition():void {
               if (videoDisplayCaptioning.captionTarget == null || videoDisplay == null) return;
            if(videoDisplayCaptioning.captionTarget && videoDisplayCaptioning.showCaptions){                    
                var captionTarget:DisplayObject = videoDisplayCaptioning.captionTarget;
                
                captionTarget.visible = videoDisplayCaptioning.showCaptions;
                // = TextField(captionTarget).getTextFormat(0,1);
                //trace( tf.size );
                
                var scaling:Number = videoDisplay.videoPlayer.width/videoDisplay.videoPlayer.videoWidth;
                
                if(captionTarget.parent.scaleX!=scaling) captionTarget.parent.scaleX = captionTarget.parent.scaleY = scaling;
                captionTarget.y = videoDisplay.videoHeight-5-captionTarget.height;
        
                var newPoint:Point = videoDisplay.videoPlayer.localToGlobal(new Point(0, 0));
                var newRect:Rectangle = new Rectangle(newPoint.x, newPoint.y, videoDisplay.videoPlayer.width, videoDisplay.videoPlayer.height);
                
                newPoint = videoDisplay.globalToLocal( newPoint );
                
                captionTarget.parent.x = newPoint.x;
                captionTarget.parent.y = newPoint.y;
                
                newPoint = videoControls.localToGlobal(new Point(0,0));
                
                var controlsRect:Rectangle = new Rectangle(newPoint.x, newPoint.y, videoControls.width, videoControls.height);
                
                if (captionTarget.parent != null && controlsRect.intersects(newRect)) {
                    captionTarget.parent.y -= controlsRect.intersection(newRect).height;
                }
                
                var gf:GlowFilter = new GlowFilter(0,1,2*scaling,2*scaling,10,3); 
                var dsf:DropShadowFilter = new DropShadowFilter(1*scaling,90,0,0.8,4,4,1);
                
                
                captionTarget.filters = [textStrokeFilter, dsf];
                
            }
        }
        
        private function showControls():void {
            if(slideOut.isPlaying){
                slideOut.stop();
            }
            if(!slideIn.isPlaying && videoControls.alpha!=1) {
                slideIn.play([videoControls]);
            }
            adjustCaptionTargetPosition();
        }
         
        private function hideControls():void {
            if(this.videoDisplay.state=="stopped"){
                return;
            }
            
            if(slideIn.isPlaying){
                slideIn.stop();
            }
            if(!slideOut.isPlaying && videoControls.alpha!=0) {
                slideOut.play([videoControls]);
            }
            adjustCaptionTargetPosition();
        }
        
        
        
        private function fullScreenHandler(evt:FullScreenEvent):void {
            slideOut.stop();
            slideIn.stop();
            dispState = Application.application.stage.displayState + " (fullScreen=" + evt.fullScreen.toString() + ")";
            if (evt.fullScreen) {
                /* Do something specific here if we switched to full screen mode. */
                fullScreenButton.selected = true;
                
            } else {
                /* Do something specific here if we switched to normal mode. */
                fullScreenButton.selected = false;
            }
            Application.application.invalidateSize();
            videoControls.percentWidth=100;
            videoControls.setConstraintValue("bottom",0);
            adjustCaptionTargetPosition();
        
        }
        
        private function toggleFullScreen():void {
            try {
                slideOut.stop();
                slideIn.stop();
                switch (Application.application.stage.displayState) {
                    case StageDisplayState.FULL_SCREEN:
                        /* If already in full screen mode, switch to normal mode. */
                        Application.application.stage.displayState = StageDisplayState.NORMAL;
                        break;
                    default:
                        /* If not in full screen mode, switch to full screen mode. */
                        Application.application.stage.displayState = StageDisplayState.FULL_SCREEN;
                        break;
                }
                videoControls.percentWidth=100;
                videoControls.setConstraintValue("bottom",0);
            } catch (err:SecurityError) {
                // ignore
            }
        }
        
        private function toggleCaptions():void {
            this.videoDisplayCaptioning.showCaptions = captionButton.selected;
            if(videoDisplayCaptioning.captionTarget){
                   videoDisplayCaptioning.captionTarget.visible = videoDisplayCaptioning.showCaptions;
               }
        }
        
        private var mute:Boolean = false;
        
        private function muteHandler(event:MouseEvent=null):void{
            
            
            if (!mute) {
                videoDisplay.volume = 0;
                mute = true;
                muteButton.selected = true;
                fadeOutVolumeSlider.play([volumeSlider]);
            }
            else{
                videoDisplay.volume = this.volumeSlider.value/100;
                mute = false;
                muteButton.selected = false;
                if(muteButton.getFocus()==muteButton){
                    fadeInVolumeSlider.play([volumeSlider]);
                }
            }
            
        }
        
        private function handleFocusIn(event:FocusEvent):void {
            showControls();
        }
        
        private function handleFocusOut(event:FocusEvent):void {
            var pt:Point = this.localToGlobal(new Point(mouseY,mouseY));
            pt = canvasWrapper.globalToLocal(pt);
            if(!canvasWrapper.hitTestPoint(pt.x,pt.y)){
                hideControls();
            }
        }
        
        private function handleVolumeFocusEvent(event:FocusEvent=null):void {
            switch(event.type){
                case FocusEvent.FOCUS_IN:
                    if(fadeOutVolumeSlider.isPlaying){
                        fadeOutVolumeSlider.stop();
                    }
                    if(!fadeInVolumeSlider.isPlaying && volumeSlider.alpha!=1  && !mute){
                        fadeInVolumeSlider.play([volumeSlider]);
                    }
                    break;
                case FocusEvent.FOCUS_OUT:
                    if(event.relatedObject!=volumeSlider && event.relatedObject != muteButton){
                        if(fadeInVolumeSlider.isPlaying){
                            fadeInVolumeSlider.stop();
                        }
                        if(!fadeOutVolumeSlider.isPlaying && volumeSlider.alpha!=0){
                            fadeOutVolumeSlider.play([volumeSlider]);
                        }
                    }
                    break;
            }
        }
        private function handleVolumeMouseEvent(event:MouseEvent=null):void {
            switch(event.type){
                case MouseEvent.ROLL_OVER:
                    if(fadeOutVolumeSlider.isPlaying){
                        fadeOutVolumeSlider.stop();
                    }
                    if(!fadeInVolumeSlider.isPlaying && volumeSlider.alpha!=1 && !mute){
                        fadeInVolumeSlider.play([volumeSlider]);
                    }
                    break;
                case MouseEvent.ROLL_OUT:
                    if(event.relatedObject!=volumeSlider && event.relatedObject != muteButton){
                        if(fadeInVolumeSlider.isPlaying){
                            fadeInVolumeSlider.stop();
                        }
                        if(!fadeOutVolumeSlider.isPlaying && volumeSlider.alpha!=0){
                            fadeOutVolumeSlider.play([volumeSlider]);
                        }
                    }
                    break;
            }
        }
        
        private function seekBarListener(e:TimerEvent):void {
        
            var scrubPos:Number = seekBar.value;
            // if called NOT on the timer, then we are done
            if (e == null) {
                _seekBarTimer.stop();
                if (scrubPos != _lastScrubPos) {
                    videoDisplay.playheadTime = seekBar.value;
                }
                videoDisplay.addEventListener(VideoEvent.PLAYHEAD_UPDATE, playheadUpdateHandler);
                if (_playAfterScrub) {
                    videoDisplay.play();
                }
                
            } else if (videoDisplay.state == "seeking") {
                // do nothing if VideoPlayer in the middle of a seek
            } else if ( _seekBarScrubTolerance <= 0 ||
                        Math.abs(scrubPos - _lastScrubPos) > _seekBarScrubTolerance ||
                        scrubPos < _seekBarScrubTolerance ||
                        scrubPos > (100 - _seekBarScrubTolerance) ) {
                if (scrubPos != _lastScrubPos) {
                    _lastScrubPos = scrubPos;
                    videoDisplay.playheadTime = seekBar.value;
                }
            }
        }
        ]]>
    </mx:Script>
    <mx:Style source="css/TimedTextAppStyles.css" />
        
    <mx:DateFormatter id="dateFormatter" formatString="NN:SS" />
    <mx:DateFormatter id="dateFormatterHours" formatString="HH:NN:SS" />
    
    <accessibility:AccessibilityProperties id="timeAcc" name="Playhead Time" /> 
    <accessibility:AccessibilityProperties id="timeRemainingAcc" name="Time Remaining" />
    <accessibility:AccessibilityProperties id="seekBarAcc" name="Seek Bar" />
    <accessibility:AccessibilityProperties id="volumeAcc" name="Volume" />

    
    <mx:Canvas id="canvasWrapper" height="100%" width="100%" autoLayout="true" rollOver="showControls()" rollOut="hideControls()">
    
        <controls:VideoDisplayPlus width="100%" height="100%" id="videoDisplay" 
            cuePointManagerClass="mx.controls.videoClasses.CuePointManager"
            autoPlay="false"
            smoothing="true" 
            playheadUpdateInterval="16" 
            playheadUpdate="playheadUpdateHandler(event)" rewind="rewindHandler(event)"
            resize="resizeHandler(event)" volume="{(muteButton.selected) ? 0 : volumeSlider.value/100}" />
            
        <videoClasses:VideoDisplayCaptioning 
            id="videoDisplayCaptioning" 
            captionChange="captionChangeHandler(CaptionChangeEvent(event))"
            autoLayout="false"
            showCaptions="true" /> 
                         
        <mx:HBox autoLayout="true" id="videoControls" blendMode="layer" styleName="videoControls" width="{canvasWrapper.width}" height="1" maxHeight="72" minHeight="1" alpha="0" bottom="0" paddingBottom="0" paddingRight="10" paddingLeft="10" horizontalScrollPolicy="off" verticalScrollPolicy="off" horizontalGap="0" verticalAlign="middle">
            
            <!-- Play/Pause Button -->
            <mx:Button id="playPauseButton"
                styleName="playPauseButton"
                label="{(playPauseButton.selected) ? 'Pause' : 'Play'}"
                tabIndex="1" 
                buttonMode="true" 
                width="51" 
                height="50" 
                labelPlacement="bottom" 
                click="playPauseClickHandler(event)"
                toggle="true"
                selected="false" />
            
            <!-- Stop Button -->
            <mx:Button id="stopButton"
                styleName="stopButton"
                label="Stop"
                tabIndex="2"  
                buttonMode="{videoDisplay.playheadTime>0}" 
                width="51" 
                height="50" 
                labelPlacement="bottom"
                enabled="{videoDisplay.playheadTime>0}"
                click="stopClickHandler(event)" />
            
            <mx:HBox width="100%" height="100%" minWidth="0" verticalAlign="middle" clipContent="true" horizontalScrollPolicy="off" verticalScrollPolicy="off">
                
                <mx:Spacer width="-10" />
                
                <!-- Time Label -->
                <mx:Label 
                    text="Playhead Time" 
                    tabIndex="3"  
                    width="1" 
                    truncateToFit="false" />
                <mx:Label id="time" 
                    styleName="timeLabelStyle"
                    text="{videoTimeConvert(videoDisplay.playheadTime)}"
                    tabIndex="4" 
                    filters="{new Array(textStrokeFilter)}" 
                    width="56" />
    
                <mx:Spacer width="-40" />
                
                <!-- SeekBar Slider -->
                <mx:HSlider id="seekBar"  
                    styleName="seekBar"
                    buttonMode="true"
                    tabIndex="5" 
                    accessibilityProperties="{seekBarAcc}"
                    width="100%"
                    minimum="{0}" 
                    maximum="{videoDisplay.totalTime}" 
                    allowTrackClick="true" 
                    liveDragging="false"
                    dataTipOffset="2" 
                    dataTipFormatFunction="videoTimeConvert"
                    showTrackHighlight="false"
                    thumbPress="seekBar_thumbPress()" 
                    thumbRelease="seekBar_thumbRelease()" 
                    mouseDown="seekBar_thumbPress()" 
                    change="seekBar_thumbRelease()"
                    sliderThumbClass="com.modernista.mx.controls.skins.StyledSliderThumb" />
                
                <mx:Spacer width="-60" />
                
                <!-- Time Remaining Label -->
                <mx:Label 
                    text="Time Remaining" 
                    tabIndex="6" 
                    width="1" 
                    truncateToFit="false" />
                <mx:Text id="timeRemaining" 
                    text="{'-'+videoTimeConvert(videoDisplay.totalTime-videoDisplay.playheadTime)}" 
                    tabIndex="7" 
                    styleName="timeLabelStyle" 
                    filters="{new Array(textStrokeFilter)}" 
                    width="66" />
            </mx:HBox>
            
            <!-- Caption Button -->
            <mx:Button id="captionButton" 
                styleName="captionButton" 
                label="{(captionButton.selected) ? 'Hide Captions' : 'Show Captions'}"
                tabIndex="8" 
                buttonMode="true" 
                width="51" 
                height="50" 
                labelPlacement="bottom" 
                click="toggleCaptions()" 
                toggle="true" 
                selected="true" />
                
            <!-- Mute Button -->
            <mx:Button id="muteButton" 
                styleName="muteButton" 
                label="{(muteButton.selected) ? 'Unmute Audio' : 'Mute Audio'}" 
                tabIndex="9" 
                buttonMode="true" 
                width="51" 
                height="50" 
                labelPlacement="bottom" 
                click="muteHandler(event)" 
                toggle="true" 
                selected="false" 
                focusIn="handleVolumeFocusEvent(FocusEvent(event))" 
                focusOut="handleVolumeFocusEvent(FocusEvent(event))" 
                rollOver="handleVolumeMouseEvent(MouseEvent(event))" 
                rollOut="handleVolumeMouseEvent(MouseEvent(event))" />
                
            <!-- Full Screen Button -->
            <mx:Button id="fullScreenButton" 
                styleName="fullScreenButton" 
                label="{(fullScreenButton.selected) ? 'Exit Full Screen' : 'Full Screen'}"
                tabIndex="11" 
                buttonMode="true" 
                width="51" 
                height="50" 
                labelPlacement="bottom" 
                click="toggleFullScreen()" 
                toggle="true" 
                selected="false" />
            
        </mx:HBox>
        
        <controls:PreVolumeSlider id="volumeSlider" 
            styleName="volumeSlider" 
            tabIndex="10" 
            accessibilityProperties="{volumeAcc}" 
            buttonMode="true" 
            bottom="{muteButton.height+volumeSlider.height+11}" 
            x="{Math.min(width-volumeSlider.width, muteButton.x+(muteButton.width-volumeSlider.width)/2)}" 
            value="70" 
            minimum="0" 
            maximum="100" 
            snapInterval="10" 
            alpha="0" 
            focusIn="handleVolumeFocusEvent(FocusEvent(event))" 
            focusOut="handleVolumeFocusEvent(FocusEvent(event))" 
            rollOver="handleVolumeMouseEvent(MouseEvent(event))" 
            rollOut="handleVolumeMouseEvent(MouseEvent(event))"
            mouseEnabled="{!muteButton.selected}"
            enabled="{!muteButton.selected}"
            tabEnabled="{!muteButton.selected}"
            focusEnabled="{!muteButton.selected}" />
    </mx:Canvas>
    
    
    <mx:Parallel id="slideOut" startDelay="1000">
        <mx:Resize heightTo="1" />
        <mx:Move yTo="{videoDisplay.y+ videoDisplay.height-1}" />
        <mx:Fade alphaTo="0" />
    </mx:Parallel>
    
    <mx:Parallel id="slideIn" startDelay="0">
        <mx:Resize heightTo="72" />
        <mx:Move yTo="{videoDisplay.y+ videoDisplay.height-72}" />
        <mx:Fade alphaTo="1" />
    </mx:Parallel>
    
    <mx:Fade id="fadeInVolumeSlider" target="volumeSlider" alphaTo="1" startDelay="500" effectStart="fadeOutVolumeSlider.stop(); fadeInVolumeSlider.stop();">
    </mx:Fade>
    <mx:Fade id="fadeOutVolumeSlider" target="volumeSlider" alphaTo="0" startDelay="1000" effectStart="fadeOutVolumeSlider.stop(); fadeInVolumeSlider.stop();">
    </mx:Fade>
    
    
</mx:Application>