/*
* Copyright 2006 Sony Computer Entertainment Inc.
*
* Licensed under the MIT Open Source License, for details please see license.txt or the website
* http://www.opensource.org/licenses/mit-license.php
*
*/

#include "ColladaConditioner.h"
unsigned int ColladaConditioner::getMaxOffset( domInputLocalOffset_Array &input_array ) {

    unsigned int maxOffset = 0;
    for ( unsigned int i = 0; i < input_array.getCount(); i++ ) {
        if ( input_array[i]->getOffset() > maxOffset ) {
            maxOffset = (unsigned int)input_array[i]->getOffset();
        }
    }
    return maxOffset;
}

void ColladaConditioner::createTrianglesFromPolylist( domMesh *thisMesh, domPolylist *thisPolylist ) {

    // Create a new <triangles> inside the mesh that has the same material as the <polylist>
    domTriangles *thisTriangles = (domTriangles *)thisMesh->createAndPlace("triangles");
    //thisTriangles->setCount( 0 );
    unsigned int triangles = 0;
    thisTriangles->setMaterial(thisPolylist->getMaterial());
    domP* p_triangles = (domP*)thisTriangles->createAndPlace("p");

    // Give the new <triangles> the same <_dae> and <parameters> as the old <polylist>
    for(int i=0; i<(int)(thisPolylist->getInput_array().getCount()); i++) {

        thisTriangles->placeElement( thisPolylist->getInput_array()[i]->clone() );
    }

    // Get the number of inputs and primitives for the polygons array
    int numberOfInputs = (int)getMaxOffset(thisPolylist->getInput_array()) + 1;
    int numberOfPrimitives = (int)(thisPolylist->getVcount()->getValue().getCount());

    unsigned int offset = 0;

    // Triangulate all the primitives, this generates all the triangles in a single <p> element
    for(int j = 0; j < numberOfPrimitives; j++) {

        int triangleCount = (int)thisPolylist->getVcount()->getValue()[j] -2;
        // Write out the primitives as triangles, just fan using the first element as the base
        int idx = numberOfInputs;
        for(int k = 0; k < triangleCount; k++) {
            // First vertex
            for(int l = 0; l < numberOfInputs; l++) {

                p_triangles->getValue().append(thisPolylist->getP()->getValue()[offset + l]);
            }
            // Second vertex
            for(int l = 0; l < numberOfInputs; l++) {

                p_triangles->getValue().append(thisPolylist->getP()->getValue()[offset + idx + l]);
            }
            // Third vertex
            idx += numberOfInputs;
            for(int l = 0; l < numberOfInputs; l++) {

                p_triangles->getValue().append(thisPolylist->getP()->getValue()[offset + idx + l]);
            }
            triangles++;
        }
        offset += (unsigned int)thisPolylist->getVcount()->getValue()[j] * numberOfInputs;
    }
    thisTriangles->setCount( triangles );

}

void ColladaConditioner::createTrianglesFromPolygons( domMesh *thisMesh, domPolygons *thisPolygons ) {

    // Create a new <triangles> inside the mesh that has the same material as the <polygons>
    domTriangles *thisTriangles = (domTriangles *)thisMesh->createAndPlace("triangles");
    thisTriangles->setCount( 0 );
    thisTriangles->setMaterial(thisPolygons->getMaterial());
    domP* p_triangles = (domP*)thisTriangles->createAndPlace("p");

    // Give the new <triangles> the same <_dae> and <parameters> as the old <polygons>
    for(int i=0; i<(int)(thisPolygons->getInput_array().getCount()); i++) {

        thisTriangles->placeElement( thisPolygons->getInput_array()[i]->clone() );
    }

    // Get the number of inputs and primitives for the polygons array
    int numberOfInputs = (int)getMaxOffset(thisPolygons->getInput_array()) +1;
    int numberOfPrimitives = (int)(thisPolygons->getP_array().getCount());

    // Triangulate all the primitives, this generates all the triangles in a single <p> element
    for(int j = 0; j < numberOfPrimitives; j++) {

        // Check the polygons for consistancy (some exported files have had the wrong number of indices)
        domP * thisPrimitive = thisPolygons->getP_array()[j];
        int elementCount = (int)(thisPrimitive->getValue().getCount());
        // Skip the invalid primitive
        if((elementCount % numberOfInputs) != 0) {
            continue;
        } else {
            int triangleCount = (elementCount/numberOfInputs)-2;
            // Write out the primitives as triangles, just fan using the first element as the base
            int idx = numberOfInputs;
            for(int k = 0; k < triangleCount; k++) {
                // First vertex
                for(int l = 0; l < numberOfInputs; l++) {

                    p_triangles->getValue().append(thisPrimitive->getValue()[l]);
                }
                // Second vertex
                for(int l = 0; l < numberOfInputs; l++) {

                    p_triangles->getValue().append(thisPrimitive->getValue()[idx + l]);
                }
                // Third vertex
                idx += numberOfInputs;
                for(int l = 0; l < numberOfInputs; l++) {

                    p_triangles->getValue().append(thisPrimitive->getValue()[idx + l]);
                }
                thisTriangles->setCount(thisTriangles->getCount()+1);
            }
        }
    }

}


bool ColladaConditioner::triangulate(DAE *dae) {

    int error = 0;

    // How many geometry elements are there?
    int geometryElementCount = (int)(dae->getDatabase()->getElementCount(NULL, "geometry" ));

    for(int currentGeometry = 0; currentGeometry < geometryElementCount; currentGeometry++) {

        // Find the next geometry element
        domGeometry *thisGeometry;
        //      error = _dae->getDatabase()->getElement((daeElement**)&thisGeometry,currentGeometry, NULL, "geometry");
        daeElement * element = 0;
        error = dae->getDatabase()->getElement(&element,currentGeometry, NULL, "geometry");
        thisGeometry = (domGeometry *) element;

        // Get the mesh out of the geometry
        domMesh *thisMesh = thisGeometry->getMesh();

        if (thisMesh == NULL){
            continue;
        }

        // Loop over all the polygon elements
        for(int currentPolygons = 0; currentPolygons < (int)(thisMesh->getPolygons_array().getCount()); currentPolygons++) {

            // Get the polygons out of the mesh
            // Always get index 0 because every pass through this loop deletes the <polygons> element as it finishes with it
            domPolygons *thisPolygons = thisMesh->getPolygons_array()[currentPolygons];
            createTrianglesFromPolygons( thisMesh, thisPolygons );
        }
        while (thisMesh->getPolygons_array().getCount() > 0) {

            domPolygons *thisPolygons = thisMesh->getPolygons_array().get(0);
            // Remove the polygons from the mesh
            thisMesh->removeChildElement(thisPolygons);
        }
        int polylistElementCount = (int)(thisMesh->getPolylist_array().getCount());
        for(int currentPolylist = 0; currentPolylist < polylistElementCount; currentPolylist++) {

            // Get the polylist out of the mesh
            // Always get index 0 because every pass through this loop deletes the <polygons> element as it finishes with it
            domPolylist *thisPolylist = thisMesh->getPolylist_array()[currentPolylist];
            createTrianglesFromPolylist( thisMesh, thisPolylist );
        }
        while (thisMesh->getPolylist_array().getCount() > 0) {

            domPolylist *thisPolylist = thisMesh->getPolylist_array().get(0);
            // Remove the polylist from the mesh
            thisMesh->removeChildElement(thisPolylist);
        }
    }
    return (error == 0);
}

bool ColladaConditioner::triangulate(const char *inputFile) {

    DAE dae;
    bool convertSuceeded = true;
    domCOLLADA* root = dae.open(inputFile);

    if (!root) {
        printf("Failed to read file %s.\n", inputFile);
        return false;
    }

    convertSuceeded = triangulate(&dae);

    dae.writeAll();
    if(!convertSuceeded) {
        printf("Encountered errors\n");
    }

    return convertSuceeded;
}

bool ColladaConditioner::stripGeometry(DAE *dae) {
    bool convertSuceeded = true;

    int error = 0;

    // How many geometry elements are there?
    int geometryElementCount = (int)(dae->getDatabase()->getElementCount(NULL, "geometry" ));
    for(int currentGeometry = 0; currentGeometry < geometryElementCount; currentGeometry++) {

        // Find the next geometry element
        domGeometry *thisGeometry = 0;
        daeElement * element = 0;
        error = dae->getDatabase()->getElement(&element, currentGeometry, NULL, "geometry");
        thisGeometry = (domGeometry *) element;

        // Get the mesh out of the geometry
        domMesh *thisMesh = thisGeometry->getMesh();

        if (thisMesh == NULL){
            continue;
        }

        daeBool removed = daeElement::removeFromParent(thisMesh);
        convertSuceeded = convertSuceeded && removed;
    }
    return convertSuceeded;
}

bool ColladaConditioner::stripGeometry(const char *inputFile) {
    DAE dae;
    bool convertSuceeded = true;
    domCOLLADA* root = dae.open(inputFile);

    if (!root) {
        printf("Failed to read file %s.\n", inputFile);
        return false;
    }

    stripGeometry(&dae);

    dae.writeAll();
    if(!convertSuceeded) {
        printf("Encountered errors\n");
    }

    return convertSuceeded;
}
