#include "OgreMaxMaterialExport.h"
#include "max.h"
#include "plugapi.h"
#include "stdmat.h"
#include "impexp.h"
#include "IGame/IGame.h"

namespace OgreMax {

    MaterialExporter::MaterialExporter(const Config& config, MaterialMap& map) : m_materialMap(map), OgreMaxExporter(config)
    {
    }

    MaterialExporter::~MaterialExporter()
    {
    }


    bool MaterialExporter::buildMaterial(std::string& output) {

        std::stringstream of;
        of.precision(6);
        of << std::fixed;
        output = "";

        if (streamMaterial(of))
            output = of.str();
        else
            return false;

        return true;
    }

    //bool MaterialExporter::streamPass(std::ostream &of, Mtl *mtl) {
    bool MaterialExporter::streamPass(std::ostream &of, IGameMaterial *mtl) {
        of << "\t\tpass" << std::endl;
        of << "\t\t{" << std::endl;

        int subMtlCt = mtl->GetSubMaterialCount();

        Point4 val4;
        Point3 val3;
        PropType pt;
        IGameProperty* p = mtl->GetAmbientData();

        if (p) {
            pt = p->GetType();

            if (pt == IGAME_POINT3_PROP) {
                p->GetPropertyValue(val3);
                of << "\t\t\tambient " << val3.x << " " << val3.y << " " << val3.z << " " << std::endl;
            }

            if (pt == IGAME_POINT4_PROP) {
                p->GetPropertyValue(val4);
                of << "\t\t\tambient " << val4.x << " " << val4.y << " " << val4.z << " " << val4.w << " " << std::endl;
            }
        }

        p = mtl->GetDiffuseData();
        if (p) {
            pt = p->GetType();

            if (pt == IGAME_POINT3_PROP) {
                p->GetPropertyValue(val3);
                of << "\t\t\tdiffuse " << val3.x << " " << val3.y << " " << val3.z << " " << std::endl;
            }

            if (pt == IGAME_POINT4_PROP) {
                p->GetPropertyValue(val4);
                of << "\t\t\tdiffuse " << val4.x << " " << val4.y << " " << val4.z << " " << val4.w << " " << std::endl;
            }
        }

        p = mtl->GetSpecularData();
        if (p) {
            pt = p->GetType();

            if (pt == IGAME_POINT3_PROP) {
                p->GetPropertyValue(val3);
                of << "\t\t\tspecular " << val3.x << " " << val3.y << " " << val3.z << " " << std::endl;
            }

            if (pt == IGAME_POINT4_PROP) {
                p->GetPropertyValue(val4);
                of << "\t\t\tspecular " << val4.x << " " << val4.y << " " << val4.z << " " << val4.w << " " << std::endl;
            }
        }

        p = mtl->GetEmissiveData();
        if (p) {
            pt = p->GetType();

            if (pt == IGAME_POINT3_PROP) {
                p->GetPropertyValue(val3);
                of << "\t\t\temissive " << val3.x << " " << val3.y << " " << val3.z << " " << std::endl;
            }

            if (pt == IGAME_POINT4_PROP) {
                p->GetPropertyValue(val4);
                of << "\t\t\temissive " << val4.x << " " << val4.y << " " << val4.z << " " << val4.w << " " << std::endl;
            }
        }

        int numTexMaps = mtl->GetNumberOfTextureMaps();
        if (numTexMaps > 0) {

            for (int texMapIdx = 0; texMapIdx < numTexMaps; texMapIdx++) {
                IGameTextureMap* tmap = mtl->GetIGameTextureMap(texMapIdx);
                if (tmap) {
                    of << "\n\t\t\ttexture_unit " << std::endl;
                    of << "\t\t\t{" << std::endl;

                    std::string bmap(tmap->GetBitmapFileName());
                    bmap = bmap.substr(bmap.find_last_of('\\') + 1);
                    of << "\t\t\t\ttexture " << bmap << std::endl;
                    of << "\t\t\t}" << std::endl;
                }
            }
        }

        of << "\t\t}" << std::endl;

        return true;
    }
    
    bool MaterialExporter::buildMaterial(IGameMaterial *material, const std::string& matName, std::string &script) {

        std::stringstream of;

        of << "material " << matName << std::endl;
        of << std::showpoint;
        of << "{" << std::endl;

        of << "\ttechnique" << std::endl;
        of << "\t{" << std::endl;

        int numSubMtl = 0;
        
        if (material != NULL) {
            numSubMtl = material->GetSubMaterialCount();

            if (numSubMtl > 0) {
                int i;
                for (i=0; i<numSubMtl; i++) {
                    streamPass(of, material->GetSubMaterial(i));
                }
            }
            else
                streamPass(of, material);
        }
        else {
            streamPass(of, material);
        }

        of << "\t}" << std::endl;
        of << "}" << std::endl;

        script = of.str();

        return true;
    }

    bool MaterialExporter::streamMaterial(std::ostream &of) {

        // serialize this information to the material file
        MaterialMap::iterator it = m_materialMap.begin();

        while (it != m_materialMap.end()) {
            std::string matName(it->first);
            IGameMaterial *mtl = it->second;

            of << "material " << matName << std::endl;
            of << std::showpoint;
            of << "{" << std::endl;

            of << "\ttechnique" << std::endl;
            of << "\t{" << std::endl;

            int numSubMtl = 0;
            
            if (mtl != NULL) {
                numSubMtl = mtl->GetSubMaterialCount();

                if (numSubMtl > 0) {
                    int i;
                    for (i=0; i<numSubMtl; i++) {
                        streamPass(of, mtl->GetSubMaterial(i));
                    }
                }
                else
                    streamPass(of, mtl);
            }
            else {
                streamPass(of, mtl);
            }

            of << "\t}" << std::endl;
            of << "}" << std::endl;

            it++;
        }

        m_materialMap.clear();

        return true;
    }

}