#include "gpuCacheMaterialNodes.h"
namespace GPUCache {
SurfaceMaterial::SurfaceMaterial(
const MString& name, 
const MString& type)
    : MaterialNode(name, type)
{
    createProperty("outColor",        MaterialProperty::kRGB, OutColor);
    createProperty("outTransparency", MaterialProperty::kRGB, OutTransparency);
}
void SurfaceMaterial::accept(MaterialNodeVisitor& visitor) const
{
    SurfaceMaterialVisitor* v = dynamic_cast<SurfaceMaterialVisitor*>(&visitor);
    if (v) {
        v->visit(*this);
    }
    else {
        assert(0);
    }
}
LambertMaterial::LambertMaterial(
const MString& name, 
const MString& type)
    : SurfaceMaterial(name, type)
{
    createProperty("color",             MaterialProperty::kRGB,   Color);
    createProperty("transparency",      MaterialProperty::kRGB,   Transparency);
    createProperty("ambientColor",      MaterialProperty::kRGB,   AmbientColor);
    createProperty("incandescence",     MaterialProperty::kRGB,   Incandescence);
    createProperty("diffuse",           MaterialProperty::kFloat, Diffuse);
    createProperty("translucence",      MaterialProperty::kFloat, Translucence);
    createProperty("translucenceDepth", MaterialProperty::kFloat, TranslucenceDepth);
    createProperty("translucenceFocus", MaterialProperty::kFloat, TranslucenceFocus);
    createProperty("hideSource",        MaterialProperty::kBool,  HideSource);
    createProperty("glowIntensity",     MaterialProperty::kFloat, GlowIntensity);
    Color->setDefault(
MColor(0.5f, 0.5f, 0.5f));
    Diffuse->setDefault(0.8f);
    TranslucenceDepth->setDefault(0.5f);
    TranslucenceFocus->setDefault(0.5f);
}
void LambertMaterial::accept(MaterialNodeVisitor& visitor) const
{
    LambertMaterialVisitor* v = dynamic_cast<LambertMaterialVisitor*>(&visitor);
    if (v) {
        v->visit(*this);
    }
    else {
        assert(0);
    }
}
PhongMaterial::PhongMaterial(
const MString& name, 
const MString& type)
    : LambertMaterial(name, type)
{
    createProperty("cosinePower",    MaterialProperty::kFloat, CosinePower);
    createProperty("specularColor",  MaterialProperty::kRGB,   SpecularColor);
    createProperty("reflectivity",   MaterialProperty::kFloat, Reflectivity);
    createProperty("reflectedColor", MaterialProperty::kRGB,   ReflectedColor);
    CosinePower->setDefault(20.0f);
    SpecularColor->setDefault(
MColor(0.5f, 0.5f, 0.5f));
    Reflectivity->setDefault(0.5f);
}
void PhongMaterial::accept(MaterialNodeVisitor& visitor) const
{
    PhongMaterialVisitor* v = dynamic_cast<PhongMaterialVisitor*>(&visitor);
    if (v) {
        v->visit(*this);
    }
    else {
        assert(0);
    }
}
BlinnMaterial::BlinnMaterial(
const MString& name, 
const MString& type)
    : LambertMaterial(name, type)
{
    createProperty("eccentricity",   MaterialProperty::kFloat, Eccentricity);
    createProperty("specularRollOff",MaterialProperty::kFloat, SpecularRollOff);
    createProperty("specularColor",  MaterialProperty::kRGB,   SpecularColor);
    createProperty("reflectivity",   MaterialProperty::kFloat, Reflectivity);
    createProperty("reflectedColor", MaterialProperty::kRGB,   ReflectedColor);
    Eccentricity->setDefault(0.3f);
    SpecularRollOff->setDefault(0.7f);
    SpecularColor->setDefault(
MColor(0.5f, 0.5f, 0.5f));
    Reflectivity->setDefault(0.5f);
}
void BlinnMaterial::accept(MaterialNodeVisitor& visitor) const
{
    BlinnMaterialVisitor* v = dynamic_cast<BlinnMaterialVisitor*>(&visitor);
    if (v) {
        v->visit(*this);
    }
    else {
        assert(0);
    }
}
    : MaterialNode(name, type)
{
    createProperty("defaultColor", MaterialProperty::kRGB,   DefaultColor);
    createProperty("outColor",     MaterialProperty::kRGB,   OutColor);
    createProperty("outAlpha",     MaterialProperty::kFloat, OutAlpha);
    DefaultColor->setDefault(
MColor(0.5f, 0.5f, 0.5f));
}
void Texture2d::accept(MaterialNodeVisitor& visitor) const
{
    Texture2dVisitor* v = dynamic_cast<Texture2dVisitor*>(&visitor);
    if (v) {
        v->visit(*this);
    }
    else {
        assert(0);
    }
}
    : Texture2d(name, type)
{
    createProperty("outTransparency", MaterialProperty::kRGB, OutTransparency);
    createProperty("fileTextureName", MaterialProperty::kString, FileTextureName);
}
void FileTexture::accept(MaterialNodeVisitor& visitor) const
{
    FileTextureVisitor* v = dynamic_cast<FileTextureVisitor*>(&visitor);
    if (v) {
        v->visit(*this);
    }
    else {
        assert(0);
    }
}
UnknownMaterialNode::UnknownMaterialNode(
const MString& name, 
const MString& type)
    : MaterialNode(name, type)
{}
void UnknownMaterialNode::accept(MaterialNodeVisitor& visitor) const
{
    UnknownMaterialNodeVisitor* v = dynamic_cast<UnknownMaterialNodeVisitor*>(&visitor);
    if (v) {
        v->visit(*this);
    }
    else {
        assert(0);
    }
}
UnknownTexture2d::UnknownTexture2d(
const MString& name, 
const MString& type)
    : Texture2d(name, type)
{}
void UnknownTexture2d::accept(MaterialNodeVisitor& visitor) const
{
    UnknownTexture2dVisitor* v = dynamic_cast<UnknownTexture2dVisitor*>(&visitor);
    if (v) {
        v->visit(*this);
    }
    else {
        assert(0);
    }
}
MaterialNode::MPtr MaterialNode::create(
const MString& name, 
const MString& nodeType)
{
    if (nodeType == "surfaceShader") {
        return boost::make_shared<SurfaceMaterial>(name);
    }
    else if (nodeType == "lambert") {
        return boost::make_shared<LambertMaterial>(name);
    }
    else if (nodeType == "phong") {
        return boost::make_shared<PhongMaterial>(name);
    }
    else if (nodeType == "blinn") {
        return boost::make_shared<BlinnMaterial>(name);
    }
    else if (nodeType == "file") {
        return boost::make_shared<FileTexture>(name);
    }
    else if (nodeType == "unknownTexture2d") {
        return boost::make_shared<UnknownTexture2d>(name);
    }
    else {
        return boost::make_shared<UnknownMaterialNode>(name, nodeType);
    }
}
}