from __future__ import generators 
# Holding module for scaffolding needed to transition parsing package
# into stateless design
import os
import re
from bike.parsing.extended_ast import getRoot, Source, Package
from bike.parsing.save import queueFileToSave
from bike.parsing.load import getRootDirectory, filenameToModulePath, \
     getPathOfModuleOrPackage, getFilesForName
from bike.parsing.fastparserast import Module
from bike.parsing.save import getQueuedFile
import sys

class Cache:
    def __init__(self):
        self.reset()
    def reset(self):
        self.srcnodecache = {}
        self.typecache = {}
        self.maskedlinescache = {}

    instance = None

Cache.instance = Cache()





def getModule(filename_path):
    try:
        sourcenode = getSourceNode(filename_path)
        return sourcenode.fastparseroot
    except CantLocateSourceNodeException:
        return None
    

class CantLocateSourceNodeException: pass

def getSourceNode(filename_path):
    #print "getSourceNode:",filename_path
    sourcenode = None
    root = getRoot()
    
    try:
        sourcenode = Cache.instance.srcnodecache[filename_path]
    except KeyError:
        pass
    
    if sourcenode is None:
        sourcenode = Source.createFromFile(filename_path,
                              translateFnameToModuleName(filename_path))
    if sourcenode is None:
        raise CantLocateSourceNodeException()

    Cache.instance.srcnodecache[filename_path]=sourcenode
    return sourcenode

def updateInternalSource(filename_path,src):
    queueFileToSave(filename_path,src)

def getSourceLines(filename_path):
    return getSourceNode(filename_path).getLines()

def getSource(filename_path):
    return getSourceNode(filename_path).getSource()


def translateFnameToModuleName(filename_path):
    rootdir = getRootDirectory(filename_path)
    return filenameToModulePath(rootdir,filename_path)

def getPackage(directory_path):
    rootdir = getRootDirectory(directory_path)
    if rootdir == directory_path:
        return getRoot()
    else:
        return Package(directory_path,
                       os.path.basename(directory_path))


# scope is the scope to search from
def getModuleOrPackageUsingFQN(fqn, scope=None):
    pythonpath = getPythonPath()
    #print pythonpath,fqn
    if scope is not None:
        if not isinstance(scope,Package):
            # shouldnt happen, so dump some trace
            print "scope = "+str(scope)
            assert isinstance(scope,Package)
        pythonpath = [scope.path] + pythonpath
    filename = getPathOfModuleOrPackage(fqn,pythonpath)
    #print "filename",filename
    if filename is not None:
        if os.path.isdir(filename):
            return getPackage(filename)
        else:
            return getModule(filename)

def getPythonPath():
    return getRoot().pythonpath

def generateModuleFilenamesInPythonPath(pythonpath=None):
    if pythonpath == None:
        pythonpath = getPythonPath()
    for path in pythonpath:
        for file in getFilesForName(path):
            yield file

def getSourceNodesContainingRegex(regexstr):
    pythonpath = getPythonPath()
    regex = re.compile(regexstr)
    for fname in generateModuleFilenamesInPythonPath(pythonpath):
        try:
            f = file(fname)
            src = f.read()
        finally:
            f.close()
        if regex.search(src) is not None:
            yield getSourceNode(fname)
        
# generates (filename,matchstr) tuples
def getRegexMatchesInPythonPath(regexstr):
    #print "getRegexMatchesInPythonPath:",regexstr
    pythonpath = getPythonPath()
    regex = re.compile(regexstr)
    for fname in generateModuleFilenamesInPythonPath(pythonpath):
        matches = []
        try:
            f = file(fname)
            src = f.read()
            for match in regex.finditer(src):
                matches.append(match.group())
        finally:
            f.close()
        for matchstr in matches:
            yield fname,matchstr
            
