#!/user/bin/env python3
# invokes shadercross
# and builds shaders for samples

import os
import subprocess

from sys import platform

origDir = os.path.abspath(os.path.dirname(__file__))
repoRoot = os.path.abspath(os.path.join(origDir, "../../"))
engineRoot = os.path.abspath(os.path.join(repoRoot, 'engine'))
libRoot = os.path.abspath(os.path.join(repoRoot, 'lib'))

# a little explanation on how we find the content dir
# 1. check the path we ran this from, if there is a folder called content/ use that.
# 2. if not, walk up the dir from the current dir until we encounter 
# contentDir.txt
# then use the relative path from that

contentDir = os.path.abspath(os.path.join('.', 'content/'))

lastPath = None
if not os.path.isdir(contentDir):
    newPath = os.path.abspath('.')
    while newPath != lastPath:
        dirTxtPath = os.path.join(newPath, 'content.txt')
        if os.path.exists(dirTxtPath):
            print(dirTxtPath)
            with open(dirTxtPath) as f:
                relPath = f.read().strip()
                contentDir = os.path.abspath(os.path.join(newPath, relPath))
            break
        newPath = os.path.abspath(os.path.join('../'))
        lastPath = newPath

print("content target dir: ", contentDir)

shadercrossDir = os.path.join(libRoot, 'sdl3/shadercross/bin')

if platform == "linux" or platform == "linux2":
    shadercrossDir = os.path.join(shadercrossDir, 'linux')
elif platform == "darwin":
    shadercrossDir = os.path.join(shadercrossDir, 'osx')
elif platform == "win32":
    shadercrossDir = os.path.join(shadercrossDir, 'win64')

shadercross = os.path.join(shadercrossDir, 'shadercross')

def discoverShaders():
    rv = []
    itemlist = os.listdir(engineRoot)
    for x in itemlist:
        modRoot = os.path.abspath(os.path.join(engineRoot, x))
        if os.path.isdir(modRoot):
            shaderRoot = os.path.abspath(os.path.join(modRoot, 'shaders/'))
            if os.path.isdir(os.path.join(modRoot, 'shaders/')):
                for x in os.listdir(shaderRoot):
                    rv.append(os.path.abspath(os.path.join(shaderRoot, x)))

    return rv

def cookList(inputFiles):
    # general cooking flow I think for shaders is 
    # they will go under 
    cookedRoot = os.path.join(contentDir, '_shaders')

    # we cook into 3 formats 
    # spirv
    # msl
    # dxil

    outputFormats = [
        ('dxil', []),
        ('spv', []),
        ('msl', []),
    ]

    spvs = []

    for fmt in outputFormats:
        outdir = os.path.join(cookedRoot, fmt[0])
        for f in inputFiles:
            basefile = f[:-5]
            outfile = os.path.abspath(os.path.join(outdir, os.path.basename(basefile) + '.' + fmt[0] ))
            os.makedirs(os.path.dirname(outfile), exist_ok=True)
            cmd = [shadercross, f] + fmt[1] + [ '-o', outfile ]

            if 'spv' == fmt[0]:
                spvs.append(outfile)

            print(cmd)
            subprocess.run(cmd)

    # run spirv-cross and generate .json files
    for f in spvs:
        basefile = f[:-4]
        outdir = os.path.join(cookedRoot, '_def')
        outfile = os.path.join(outdir, os.path.basename(basefile) + '.json' )
        os.makedirs(os.path.dirname(outfile), exist_ok=True)

        cmd = ['spirv-cross',  f, '--reflect', '--output', outfile ]
        print(cmd)
        subprocess.run(cmd)

if __name__ == '__main__':
    inputFiles = discoverShaders()
    print(inputFiles)
    cookList(inputFiles)

