// Function for retreiving all the files in the given path including sub directories
Files Receiver::showFiles(const Path1& path, Patterns& patts)
{
	Files *files = new Files();
	Path *p=new Path();
	string fullpath = p->getFullFileSpec(path);
	if (!FileSystem::Directory::exists(path))
	{
		std::ostringstream out;
		out << "path " << path << "does not exist";
		throw std::exception(out.str().c_str());
	}
	std::vector<std::string> directories;
	directories.push_back(fullpath);

	showAllDirectories((fullpath), directories);

	for (auto direc : directories){
		FileSystem::Directory::setCurrentDirectory(direc);
		for (auto patt : patts)
		{
			std::string fp = FileSystem::Directory::getCurrentDirectory();
			std::vector<std::string> temp = FileSystem::Directory::getFiles(FileSystem::Directory::getCurrentDirectory(), patt);
			for (size_t i = 0; i < temp.size(); i++){
				temp[i] = fp + "\\" + temp[i];      
			}
			files->insert(files->end(), temp.begin(), temp.end());
		}
	}
	return *files;
}
    bool readMasterFile(Files& files) const
    {
        osgDB::ifstream fin(_filename.c_str());
        if (fin)
        {
            osgDB::Input fr;
            fr.attach(&fin);

            bool readFilename = false;

            while(!fr.eof())
            {
                bool itrAdvanced = false;
                if (fr.matchSequence("file %s") || fr.matchSequence("file %w") )
                {
                    files.insert(fr[1].getStr());
                    fr += 2;
                    itrAdvanced = true;
                    readFilename = true;
                }

                if (!itrAdvanced)
                {
                    ++fr;
                }
            }

            return readFilename;
        }
        return false;
    }
    void load()
    {
        //osg::notify(osg::NOTICE)<<"void load(Object)"<<std::endl;
        Files filesA;
        Files filesB;

        readMasterFile(filesB);
        // osg::notify(osg::NOTICE)<<"First read "<<filesA.size()<<std::endl;

        // itererate until the master file is stable
        do
        {
            OpenThreads::Thread::microSleep(100000);

            filesB.swap(filesA);
            filesB.clear();
            readMasterFile(filesB);

            // osg::notify(osg::NOTICE)<<"second read "<<filesB.size()<<std::endl;

        } while (filesA!=filesB);

        Files files;
        files.swap(filesB);

        // osg::notify(osg::NOTICE)<<"Now equal "<<files.size()<<std::endl;


        Files newFiles;
        Files removedFiles;

        // find out which files are new, and which ones have been removed.
        {
            OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);

            for(Files::iterator fitr = files.begin();
                fitr != files.end();
                ++fitr)
            {
                if (_existingFilenameNodeMap.count(*fitr)==0) newFiles.insert(*fitr);
            }

            for(FilenameNodeMap::iterator litr = _existingFilenameNodeMap.begin();
                litr != _existingFilenameNodeMap.end();
                ++litr)
            {
                if (files.count(litr->first)==0)
                {
                    removedFiles.insert(litr->first);
                }
            }
        }

#if 0
        if (!newFiles.empty() || !removedFiles.empty())
        {
            osg::notify(osg::NOTICE)<<std::endl<<std::endl<<"void operator () files.size()="<<files.size()<<std::endl;
        }
#endif

        // first load the new files.
        FilenameNodeMap nodesToAdd;
        if (!newFiles.empty())
        {

            typedef std::vector< osg::ref_ptr<osg::GraphicsThread> > GraphicsThreads;
            GraphicsThreads threads;

            for(unsigned int i=0; i<= osg::GraphicsContext::getMaxContextID(); ++i)
            {
                osg::GraphicsContext* gc = osg::GraphicsContext::getCompileContext(i);
                osg::GraphicsThread* gt = gc ? gc->getGraphicsThread() : 0;
                if (gt) threads.push_back(gt);
            }

            if (_operationQueue.valid())
            {
                // osg::notify(osg::NOTICE)<<"Using OperationQueue"<<std::endl;

                _endOfLoadBlock = new osg::RefBlockCount(newFiles.size());

                _endOfLoadBlock->reset();

                typedef std::list< osg::ref_ptr<LoadAndCompileOperation> > LoadAndCompileList;
                LoadAndCompileList loadAndCompileList;

                for(Files::iterator nitr = newFiles.begin();
                    nitr != newFiles.end();
                    ++nitr)
                {
                    // osg::notify(osg::NOTICE)<<"Adding LoadAndCompileOperation "<<*nitr<<std::endl;

                    osg::ref_ptr<LoadAndCompileOperation> loadAndCompile = new LoadAndCompileOperation( *nitr, _incrementalCompileOperation.get(), _endOfLoadBlock.get() );
                    loadAndCompileList.push_back(loadAndCompile);
                    _operationQueue->add( loadAndCompile.get() );
                }

#if 1
                osg::ref_ptr<osg::Operation> operation;
                while ((operation=_operationQueue->getNextOperation()).valid())
                {
                    // osg::notify(osg::NOTICE)<<"Local running of operation"<<std::endl;
                    (*operation)(0);
                }
#endif
                // osg::notify(osg::NOTICE)<<"Waiting for completion of LoadAndCompile operations"<<std::endl;
                _endOfLoadBlock->block();
                // osg::notify(osg::NOTICE)<<"done ... Waiting for completion of LoadAndCompile operations"<<std::endl;

                for(LoadAndCompileList::iterator litr = loadAndCompileList.begin();
                    litr != loadAndCompileList.end();
                    ++litr)
                {
                    if ((*litr)->_loadedModel.valid())
                    {
                        nodesToAdd[(*litr)->_filename] = (*litr)->_loadedModel;
                    }
                }

            }

            else
            {

                _endOfLoadBlock = new osg::RefBlockCount(newFiles.size());

                _endOfLoadBlock->reset();

                for(Files::iterator nitr = newFiles.begin();
                    nitr != newFiles.end();
                    ++nitr)
                {
                    osg::ref_ptr<osg::Node> loadedModel = osgDB::readRefNodeFile(*nitr);

                    if (loadedModel.get())
                    {
                        nodesToAdd[*nitr] = loadedModel;

                        if (_incrementalCompileOperation.valid())
                        {
                            osg::ref_ptr<osgUtil::IncrementalCompileOperation::CompileSet> compileSet =
                                new osgUtil::IncrementalCompileOperation::CompileSet(loadedModel.get());

                            compileSet->_compileCompletedCallback = new ReleaseBlockOnCompileCompleted(_endOfLoadBlock.get());

                            _incrementalCompileOperation->add(compileSet.get());
                        }
                        else
                        {
                            _endOfLoadBlock->completed();
                        }
                    }
                    else
                    {
                        _endOfLoadBlock->completed();
                    }
                }

                _endOfLoadBlock->block();

            }

        }

        bool requiresBlock = false;

        // pass the locally peppared data to MasterOperations shared data
        // so that updated thread can merge these changes with the main scene
        // graph.  This merge is carried out via the update(..) method.
        if (!removedFiles.empty() || !nodesToAdd.empty())
        {
            OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
            _nodesToRemove.swap(removedFiles);
            _nodesToAdd.swap(nodesToAdd);
            requiresBlock = true;
        }

        // now block so we don't try to load anything till the new data has been merged
        // otherwise _existingFilenameNodeMap will get out of sync.
        if (requiresBlock)
        {
            _updatesMergedBlock.block();
        }
        else
        {
            OpenThreads::Thread::YieldCurrentThread();
        }

    }