    package uk.co.mikecann.managers
    {
        import com.adobe.serialization.json.JSON;

        import flash.events.Event;
        import flash.events.FileListEvent;
        import flash.events.IEventDispatcher;
        import flash.filesystem.File;
        import flash.filesystem.FileMode;
        import flash.filesystem.FileStream;

        import mx.collections.ArrayCollection;

        import uk.co.mikecann.consts.Consts;
        import uk.co.mikecann.events.SourcesEvent;
        import uk.co.mikecann.models.AudioBookModel;

        public class ABOManager
        {

            // Publics
            [Bindable]public var sources : ArrayCollection;
            [Bindable]public var books : ArrayCollection;

            // Privates
            private var _dispatcher : IEventDispatcher;
            private var _bookLibrary : Array;

            public function ABOManager(d:IEventDispatcher)
            {
                _dispatcher = d;
                sources = new ArrayCollection();
                books = new ArrayCollection();
                loadPersistantData();
            }

            public function addSource() : void
            {
                var file:File = new File();
                file.addEventListener(Event.SELECT, onDirSelected);
                file.browseForDirectory("Select a directory");
                saveBooklist();
            }

            private function onDirSelected(e:Event) : void
            {
                sources.addItem(File(e.target).nativePath);
                _dispatcher.dispatchEvent(new SourcesEvent(SourcesEvent.CHANGED));
            }

            public function removeSource(src:String) : void
            {
                var indx : int = sources.getItemIndex(src);
                if (indx<0){return;}
                sources.removeItemAt(indx);
                _dispatcher.dispatchEvent(new SourcesEvent(SourcesEvent.CHANGED));
            }

            public function rebuildBookList() : void
            {
                // empty list
                books.removeAll();

                // loop through all sources rebuilding list
                for(var i:int=0; i<sources.length; i++)
                {
                    var dir:File = new File(sources[i]);
                    if (!dir.exists){continue;}
                    dir.addEventListener(FileListEvent.DIRECTORY_LISTING, onDirList);
                    dir.getDirectoryListingAsync();
                }
            }

            private function onDirList(event:FileListEvent) : void
            {
                var contents:Array = event.files;
                for (var i:uint = 0; i < contents.length; i++)
                {
                    var f  : File = contents[i];
                    if (!f.isDirectory){continue;} // only interested in directories

                    var libabm : AudioBookModel = checkLibraryForBook(contents[i].name);
                    if (libabm==null)
                    {
                        var abm : AudioBookModel = new AudioBookModel();
                        abm.name = contents[i].name;
                        abm.listened = false;
                        abm.rating = 0;
                        books.addItem(abm);
                    }
                    else
                    {
                        books.addItem(libabm);
                    }
                }
            }

            private function checkLibraryForBook(bookName:String) : AudioBookModel
            {
                for(var i:int=0; i<_bookLibrary.length; i++)
                {
                    var abm : AudioBookModel = AudioBookModel(_bookLibrary[i]);
                    if (abm.name==bookName){ return abm; }
                }
                return null;
            }

            public function loadPersistantData() : void
            {
                // First things first
                _bookLibrary = [];

                // Try to get data file
                var data : File = new File(File.applicationStorageDirectory.url+"data.json");

                // If the file doesnt exist get the hell out
                if (!data.exists){ return; }

                // Read the object bugger
                var fileStream:FileStream = new FileStream();
                fileStream.open(data, FileMode.READ);
                var o : Object = fileStream.readObject();
                fileStream.close();

                // for all the books in the saved data
                for(var i:int=0; i<o.books.length; i++)
                {
                    var abm : AudioBookModel = new AudioBookModel();
                    abm.listened = o.books[i].listened;
                    abm.name = o.books[i].name;
                    abm.rating = o.books[i].rating;
                    _bookLibrary.push(abm);
                }

                // grab the sources
                sources = new ArrayCollection(o.sources);
                rebuildBookList();
            }

            public function saveBooklist() : void
            {
                var data : File = new File(File.applicationStorageDirectory.url+"data.json");

                // Remove the file if its there we are gonna fill it
                if (data.exists){ data.deleteFile(); }

                // Write data to string
                var o : Object = {};
                o.version = Consts.VERSION;
                o.books = books.toArray();
                o.sources = sources.toArray();
                var s : String = JSON.encode(o);

                // Write to the bugger
                var fileStream:FileStream = new FileStream();
                fileStream.open(data, FileMode.WRITE);
                fileStream.writeObject(o);
                fileStream.close();
            }

            public function resetAll() : void
            {
                // Delte the data file
                var data : File = new File(File.applicationStorageDirectory.url+"data.json");
                if (data.exists){ data.deleteFile(); }

                // Empty all lists
                _bookLibrary = [];
                sources.removeAll();
                books.removeAll();
            }
        }
    }