<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
                       xmlns:s="library://ns.adobe.com/flex/spark" 
                       xmlns:mx="library://ns.adobe.com/flex/halo"
                       applicationComplete="init(event)" viewSourceURL="srcview/index.html">
    <fx:Script>
        <![CDATA[
            import flash.events.Event;
            import flash.events.ProgressEvent;
            import flash.net.URLRequest;
            import flash.net.URLStream;
            import flash.utils.ByteArray;
            
            import mx.controls.Alert;
            import mx.events.FlexEvent;
            
            private var urlStream:URLStream;
            private var fData:ByteArray;
            
            private var bytesLoaded:Number = 0;
            private var totalBytesLoaded:Number = 0;
            private var bytesTotal:Number = 0;
            
            private var fileName:String = '';
            private var file:File;
            
            protected function init(event:FlexEvent):void
            {
                urlStream = new URLStream;
                urlStream.addEventListener(ProgressEvent.PROGRESS, onProgress);
                urlStream.addEventListener(Event.COMPLETE, onComplete);
            }
            
            private function startDownload():void
            {
                bytesLoaded = 0;
                bytesTotal = 0;
                totalBytesLoaded = 0;
                
                var url:String = fileInput.text;
                var index:int = url.lastIndexOf('/');
                fileName = url.substring(index+1, url.length);
                file = File.desktopDirectory.resolvePath(fileName);
                status = file.url;
                if(file.exists)
                {
                    btn.label = 'Download';
                    mx.controls.Alert.show('Please remove "'+fileName+'" from your disk', 'File with the same name already exists');
                    return;
                }
                output.text += 'Downloading...\n';
                
                urlStream.load( new URLRequest(url) );
                fData = new ByteArray;
                fileInput.enabled = false; 
            }
            
            private function pauseDownload():void
            {
                output.text += 'Downloading is paused\n';
                if(urlStream.connected) 
                    urlStream.close();
                
                totalBytesLoaded += bytesLoaded;
                writeFile();
            }
            
            private function resumeDownload():void
            {
                output.text += 'Downloading...\n';
                var header0:URLRequestHeader = new URLRequestHeader('range', 'bytes='+totalBytesLoaded+'-'+bytesTotal);
                var request:URLRequest = new URLRequest(fileInput.text);
                request.requestHeaders.push(header0);
                
                urlStream.load( request );
                fData = new ByteArray;
            }
            
            private function onProgress(event:ProgressEvent):void
            {
                bytesLoaded = event.bytesLoaded;
                if(bytesTotal != event.bytesTotal)
                    bytesTotal = event.bytesTotal;
                
                progressBar.setProgress( (totalBytesLoaded + event.bytesLoaded) / event.bytesTotal, progressBar.maximum);
                
                if(urlStream.bytesAvailable == 0) return;
                if(urlStream.connected) urlStream.readBytes(fData, fData.length);
            }
            
            private function onComplete(event:Event):void
            {
                output.text += 'Download complete\n';
                bytesLoaded = 0;
                bytesTotal = 0;
                totalBytesLoaded = 0;
                progressBar.setProgress(0, 1);
                
                if(urlStream.connected)
                    urlStream.close();
                
                writeFile();
                fileInput.enabled = true;
                btn.label = 'Download';
            }
            
            private function writeFile():void
            {
                output.text += 'Saving File...\n';
                var fileStream:FileStream = new FileStream;
                fileStream.open(file, file.exists ? FileMode.APPEND:FileMode.WRITE);
                fileStream.writeBytes(fData);
                fileStream.close();
                output.text += 'File Saved\n';
            }
            
            private function btnClickHandler():void
            {
                if(bytesLoaded == 0)
                {
                    btn.label = 'Pause';
                    startDownload();
                }
                else
                {
                    if(urlStream.connected)
                    {
                        btn.label = 'Resume';
                        pauseDownload();
                    }
                    else
                    {
                        btn.label = 'Pause';
                        resumeDownload();
                    }
                }
            }
        ]]>
    </fx:Script>
    <s:TextInput id="fileInput" y="15" left="67" right="10"/>
    <s:Button id="btn" x="286" y="65" label="Download" click="btnClickHandler()"/>
    <mx:ProgressBar id="progressBar" x="67" y="65" 
                    mode="manual" minimum="0" maximum="1" label="Downloading %3%%"/>
    <s:Label x="10" y="20" text="File URL"/>
    <s:TextArea id="output" left="10" right="10" top="107" bottom="10"/>
    <s:Button y="65" label="Clear Input" right="10" 
              enabled="{fileInput.text.length==0 ? false:fileInput.enabled}"
              click="fileInput.text = ''"/>
    <s:Label x="67" y="46" 
             text="http://www.example.com/downloads/episode77.mp3" 
             color="#878787"/>
</s:WindowedApplication>