import os
import ycm_core
# Defaults, if no database can be found.
defaultsc = [
        'gcc',
        '-Wno-long-long',
        '-Wno-variadic-macros',
        '-pthread'
        '-std=c99',
        ]
defaultscpp = [
        'c'
        '-Wno-long-long',
        '-Wno-variadic-macros',
        '-pthread'
        '-std=c99',
        ]

# Things that must be included.
entered_flags = ['-fdelayed-template-parsing']

#
def DirectoryOfThisScript():
    return os.path.dirname( os.path.abspath( __file__ ) )

# Find all compilation databases in the build directory and load them.

def MakeRelativePathsInFlagsAbsolute( flags, working_directory ):
  if not working_directory:
    return list( flags )
  new_flags = []
  make_next_absolute = False
  path_flags = [ '-isystem', '-I', '-iquote', '--sysroot=' ]
  for flag in flags:
    new_flag = flag

    if make_next_absolute:
      make_next_absolute = False
      if not flag.startswith( '/' ):
        new_flag = os.path.join( working_directory, flag )

    for path_flag in path_flags:
      if flag == path_flag:
        make_next_absolute = True
        break

      if flag.startswith( path_flag ):
        path = flag[ len( path_flag ): ]
        new_flag = path_flag + os.path.join( working_directory, path )
        break

    if new_flag:
      new_flags.append( new_flag )
  return new_flags


def FlagsForFile( filename ):
    # Search through all parent directories for a directory named 'build'
    databases = []
    path_focus = os.path.dirname(filename)
    while len(path_focus) > 1:
        for f in os.listdir(path_focus):
            compilation_database_folder = path_focus + "/" + f
            for r,d,f in os.walk(compilation_database_folder):
                for files in f:
                    if files == 'compile_commands.json':
                        databases += [ycm_core.CompilationDatabase( r )]
        path_focus = os.path.dirname(os.path.dirname(path_focus))

    # Use a header's source file database for completion.
    filetype_flags = []
    if filename.endswith(".h"):
        for f in os.listdir(os.path.dirname(filename)):
            if filename.replace(".h",".cpp").find(f) != -1:
                filename = filename.replace(".h",".cpp")
                break
            if filename.replace(".h",".c").find(f) != -1:
                filename = filename.replace(".h",".c")
                break
    elif filename.endswith(".hpp"):
        for f in os.listdir(os.path.dirname(filename)):
            if filename.replace(".hpp",".cpp").find(f) != -1:
                filename = filename.replace(".hpp",".cpp")
                break

    # Get the compile commands
    final_flags = []
    # If possible, from the database.
    if len(databases) > 0:
        for database in databases:
            compilation_info = database.GetCompilationInfoForFile( filename )
            fromfile_flags = MakeRelativePathsInFlagsAbsolute(
            compilation_info.compiler_flags_,
            compilation_info.compiler_working_dir_ )
            final_flags += fromfile_flags

    # If not, set some sane defaults.
    else:
        relative_to = DirectoryOfThisScript()
        final_flags += MakeRelativePathsInFlagsAbsolute( flags, relative_to )
    if not final_flags:
        if filename.endswith(".c"):
            final_flags = defaultsc
        elif filename.endswith(".cpp"):
            final_flags = defaultscpp

    # This allows header files to be parsed according to their parent source
    final_flags = filetype_flags + final_flags

    # For things that must be included regardless:
    final_flags += entered_flags
    return {
        'flags': final_flags,
        'do_cache': True
    }