#include "OgreSGTechniqueResolverListener.h"

#include "OgreTechnique.h"

namespace OgreBites {

SGTechniqueResolverListener::SGTechniqueResolverListener(Ogre::RTShader::ShaderGenerator *pShaderGenerator)
{
    mShaderGenerator = pShaderGenerator;
}

Ogre::Technique *SGTechniqueResolverListener::handleSchemeNotFound(unsigned short schemeIndex, const Ogre::String &schemeName, Ogre::Material *originalMaterial, unsigned short lodIndex, const Ogre::Renderable *rend) {
    if (!mShaderGenerator->hasRenderState(schemeName))
    {
        return NULL;
    }
    // Case this is the default shader generator scheme.

    // Create shader generated technique for this material.
    bool techniqueCreated = mShaderGenerator->createShaderBasedTechnique(
                *originalMaterial,
                Ogre::MaterialManager::DEFAULT_SCHEME_NAME,
                schemeName);

    if (!techniqueCreated)
    {
        return NULL;
    }
    // Case technique registration succeeded.

    // Force creating the shaders for the generated technique.
    mShaderGenerator->validateMaterial(schemeName, *originalMaterial);

    // Grab the generated technique.
    for(auto *t : originalMaterial->getTechniques())
    {
        if (t->getSchemeName() == schemeName)
        {
            return t;
        }
    }

    return NULL;
}

bool SGTechniqueResolverListener::afterIlluminationPassesCreated(Ogre::Technique *tech)
{
    if(mShaderGenerator->hasRenderState(tech->getSchemeName()))
    {
        Ogre::Material* mat = tech->getParent();
        mShaderGenerator->validateMaterialIlluminationPasses(tech->getSchemeName(),
                                                             mat->getName(), mat->getGroup());
        return true;
    }
    return false;
}

bool SGTechniqueResolverListener::beforeIlluminationPassesCleared(Ogre::Technique *tech)
{
    if(mShaderGenerator->hasRenderState(tech->getSchemeName()))
    {
        Ogre::Material* mat = tech->getParent();
        mShaderGenerator->invalidateMaterialIlluminationPasses(tech->getSchemeName(),
                                                               mat->getName(), mat->getGroup());
        return true;
    }
    return false;
}

}
