# Copyright 2016 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

from __future__ import print_function

import os
import glob
import re
import sys
from shutil import copyfile

# Helpers
def ensureExists(path):
    try:
        os.makedirs(path)
    except OSError:
        pass

def writeLinesToFile(lines, fileName):
    ensureExists(os.path.dirname(fileName))
    with open(fileName, "w") as f:
        f.writelines(lines)

def extractIdg(projFileName):
    result = []
    with open(projFileName) as projFile:
        lines = iter(projFile)
        for pLine in lines:
            if "<ItemDefinitionGroup" in pLine:
                while not "</ItemDefinitionGroup" in pLine:
                    result.append(pLine)
                    pLine = next(lines)
                result.append(pLine)
                return result

# [ (name, hasSln), ... ]
configs = []

# Find all directories that can be used as configs (and record if they have VS
# files present)
for root, dirs, files in os.walk("out"):
    for outDir in dirs:
        gnFile = os.path.join("out", outDir, "build.ninja.d")
        if os.path.exists(gnFile):
            slnFile = os.path.join("out", outDir, "all.sln")
            configs.append((outDir, os.path.exists(slnFile)))
    break

# Every project has a GUID that encodes the type. We only care about C++.
cppTypeGuid = "8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942"

# name -> [ (config, pathToProject, GUID), ... ]
allProjects = {}
projectPattern = (r'Project\("\{' + cppTypeGuid +
                  r'\}"\) = "([^"]*)", "([^"]*)", "\{([^\}]*)\}"')
projectNamePattern = (r'obj/(.*)\.vcxproj')

for config in configs:
    if config[1]:
        slnLines = iter(open("out/" + config[0] + "/all.sln"))
        for slnLine in slnLines:
            matchObj = re.match(projectPattern, slnLine)
            if matchObj:
                projPath = matchObj.group(2)
                nameObj = re.match(projectNamePattern, projPath)
                if nameObj:
                    projName = nameObj.group(1).replace('/', '.')
                    if projName not in allProjects:
                        allProjects[projName] = []
                    allProjects[projName].append((config[0], projPath,
                                                 matchObj.group(3)))

# We need something to work with. Typically, this will fail if no GN folders
# have IDE files
if len(allProjects) == 0:
    print("ERROR: At least one GN directory must have been built with --ide=vs")
    sys.exit()

# Create a new solution. We arbitrarily use the first config as the GUID source
# (but we need to match that behavior later, when we copy/generate the project
# files).
newSlnLines = []
newSlnLines.append(
    'Microsoft Visual Studio Solution File, Format Version 12.00\n')
newSlnLines.append('# Visual Studio 2015\n')
for projName, projConfigs in allProjects.items():
    newSlnLines.append('Project("{' + cppTypeGuid + '}") = "' + projName +
                       '", "' + projConfigs[0][1] + '", "{' + projConfigs[0][2]
                       + '}"\n')
    newSlnLines.append('EndProject\n')

newSlnLines.append('Global\n')
newSlnLines.append(
    '\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n')
for config in configs:
    newSlnLines.append('\t\t' + config[0] + '|x64 = ' + config[0] + '|x64\n')
newSlnLines.append('\tEndGlobalSection\n')
newSlnLines.append(
    '\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n')
for projName, projConfigs in allProjects.items():
    projGuid = projConfigs[0][2]
    for config in configs:
        newSlnLines.append('\t\t{' + projGuid + '}.' + config[0] +
                           '|x64.ActiveCfg = ' + config[0] + '|x64\n')
        newSlnLines.append('\t\t{' + projGuid + '}.' + config[0] +
                           '|x64.Build.0 = ' + config[0] + '|x64\n')
newSlnLines.append('\tEndGlobalSection\n')
newSlnLines.append('\tGlobalSection(SolutionProperties) = preSolution\n')
newSlnLines.append('\t\tHideSolutionNode = FALSE\n')
newSlnLines.append('\tEndGlobalSection\n')
newSlnLines.append('\tGlobalSection(NestedProjects) = preSolution\n')
newSlnLines.append('\tEndGlobalSection\n')
newSlnLines.append('EndGlobal\n')

# Write solution file
writeLinesToFile(newSlnLines, "out/sln/skia.sln")

idgHdr = "<ItemDefinitionGroup Condition=\"'$(Configuration)|$(Platform)'=='"

# Now, bring over the project files
for projName, projConfigs in allProjects.items():
    # Paths to project and filter file in src and dst locations
    srcProjPath = os.path.join("out", projConfigs[0][0], projConfigs[0][1])
    dstProjPath = os.path.join("out", "sln", projConfigs[0][1])
    srcFilterPath = srcProjPath + ".filters"
    dstFilterPath = dstProjPath + ".filters"

    # Copy the filter file unmodified
    ensureExists(os.path.dirname(dstProjPath))
    copyfile(srcFilterPath, dstFilterPath)

    # Bring over the project file, modified with extra configs
    with open(srcProjPath) as srcProjFile:
        projLines = iter(srcProjFile)
        newProjLines = []
        for line in projLines:
            if "<ItemDefinitionGroup" in line:
                # This is a large group that contains many settings. We need to
                # replicate it, with conditions so it varies per configuration.
                idgLines = []
                while not "</ItemDefinitionGroup" in line:
                    idgLines.append(line)
                    line = next(projLines)
                idgLines.append(line)
                for projConfig in projConfigs:
                    configIdgLines = extractIdg(os.path.join("out",
                                                             projConfig[0],
                                                             projConfig[1]))
                    newProjLines.append(idgHdr + projConfig[0] + "|x64'\">\n")
                    for idgLine in configIdgLines[1:]:
                        newProjLines.append(idgLine)
            elif "ProjectConfigurations" in line:
                newProjLines.append(line)
                projConfigLines = [
                    next(projLines),
                    next(projLines),
                    next(projLines),
                    next(projLines) ]
                for config in configs:
                    for projConfigLine in projConfigLines:
                        newProjLines.append(projConfigLine.replace("GN",
                                                                   config[0]))
            elif "<OutDir" in line:
                newProjLines.append(line.replace(projConfigs[0][0],
                                                 "$(Configuration)"))
            else:
                newProjLines.append(line)
        with open(dstProjPath, "w") as newProj:
            newProj.writelines(newProjLines)
