/*****************************************************************************
 * This is the main code of a DeleD export plugin template for C++.          *
 * Author: Salvatore Russo "Il Buzzo"                                        *
 * Version: 1.2.0                                                            *
 * DeleD version: 1.1.0                                                      *
 * License: GNU General Public License.                                      *
 * Made with: Dev-Cpp 4.9.9.2 and MinGW (Tested with GCC 3.3.1, GCC 3.2.2    *
 *            and GCC 3.4.2)                                                 *
 * Link Libraries: libcomdlg32.a (it includes calling to OpenDialog etc..)   *
 * Linker parameters: --no-export-all-symbols --add-stdcall-alias            *
 * Additional Compiler Parameters: -DBUILDING_DLL=1                          *
 * End Notes: This is an adaptation to new plugin system, so there are some  *
 *            changes from the old code, but as result I'm still adding to   *
 *            to code try{}catch() blocks for a better error handling.       *
 *            It's not so difficult so if you don't want to wait for another *
 *            version you can implement it without difficulty.               *
 *****************************************************************************/

    //Main header
#include "dll.h"
    //Necessary for DLL to work
#include <windows.h>

    //support.h contains some classes used, defined by me
    //like String and StringList and some defined for DeleD
    //in Jeroen sample code.
    //Look at that file for major details.
#include "support.h"


    //TCallBack variable used to receive a pointer by DeleD
TCallBack callback;

    /* EXPORTED FUNCTIONS NECESSARY TO DELED
    
    PCHAR PluginName() : returns name of Plugin
    PCHAR PluginDescription() : returns a small description of Plugin
    PCHAR PluginDeleDVersion() : returns version of DeleD
    PCHAR PluginVersion() : returns version of Plugin
    PCHAR PluginAuthor() : returns Author's name
    PCHAR PluginEmail() : returns Author's e-mail
    void PluginSetCallback(void*cp) : pass callback pointer from DeleD to callback
    void PluginExecute() : it executes plugin code
    
    notes:
        PCHAR is the same as char* so it's a null terminated c string.
        Each function is defined as DLLEXPORT for major details see
        the DLLEXPORT definition in dll.h file.
        As you can notice the function PluginType() is no longer used.
    */


DLLEXPORT PCHAR PluginName(){
    return "DeleD Export Plugin Sample";
}    

DLLEXPORT PCHAR PluginDescription(){
    return "This is just a sample to test main plugin system functionality.";
}

DLLEXPORT PCHAR PluginDeleDVersion(){
    return "1.1";
}    

DLLEXPORT PCHAR PluginVersion(){
    return "1.0";
}    

DLLEXPORT PCHAR PluginAuthor(){
    return "Your Name";
}    

DLLEXPORT PCHAR PluginEmail(){
    return "youremail@yourdomain";
}
    
DLLEXPORT void PluginSetCallback(void *cp){
    callback=TCallBack(cp);
}

DLLEXPORT void PluginExecute(){
   //variables used
    TCbData cbData;//callback data
    
    //create a structure for Save Dialog (salva is the italian word for save :-))
    OPENFILENAME salva;
    
    //create a buffer for file name and path I hope it's big enough :-)
    char szFile[512];
    
    //inizialize structures to zeros
    ZeroMemory(&salva, sizeof(OPENFILENAME));
    ZeroMemory(szFile, 512*sizeof(char));
    
    //initialization of structure salva
    salva.lStructSize = sizeof(OPENFILENAME);
    salva.hwndOwner = NULL;//Parent window
    salva.lpstrFile = szFile;//file name buffer
    salva.nMaxFile = 512;//buffer size
    salva.lpstrFilter = "DMF Files(*.dmf)\0*.dmf\0Text files(*.txt)\0*.txt\0All files(*.*)\0*.*\0";//filter data
    salva.nFilterIndex = 1;//default index
    salva.lpstrFileTitle = NULL;
    salva.lpstrTitle = "Select a file to export data string from DeleD";//Save dialog title
    salva.lpstrInitialDir = NULL;
    salva.Flags = OFN_OVERWRITEPROMPT;//ask to overwrite an existent file


    //First of all we'll try to get DeleD directory to know where textures
    //are located and then we'll create a string containing material data
    
    
    String DeleDir;//DeleD directory
    DeleDir.clear();
    
    //just a simple sample code to show DeleD install dir
    try{
        unsigned error;// errors returned by callback
        cbData.Reason = PR_GETINSTALLDIR;//reason of callback
        cbData.Data = new char[512];//allocate new space for string
        error=callback(&cbData);//pass Data to callback retrieving eventual errors
        if(!error){//if no errors detected then go on
            String myStr;//get directory
            DeleDir=String(cbData.Data);
            MessageBox(NULL,DeleDir.c_str(),"DeleD install dir:",MB_ICONINFORMATION);//show info 
        }
        else throw error;//if errors generate an exception    
        delete cbData.Data;//destroy previously allocated memory
    }
    catch( unsigned exception) {
        ErrorMessage(exception);//show error message (you can use this block to handle errors)    
    }    
    
    //Now we do the real job of retrieving data by asking DeleD how many
    //space I need to allocate to get selected objects in example
    if(GetSaveFileName(&salva)) {
        try{
        unsigned errors;// errors returned by callback
        String myStr;
        myStr.clear();
        if(MessageBox(NULL,"Do you want to export all objects in this scene?\nIf so click yes or no if you want just to export selection.","Export All Objects?",MB_YESNO|MB_ICONINFORMATION)==IDYES){
        myStr = String("2;091;3,0,0,0;1,0,0,0;");//number of headers ;version;items wanted (materials), set to 0 number of items,offset and length;items wanted (all objects), set to 0 number of items,offset and length;
        }    
        else myStr = String("2;091;3,0,0,0;10,0,0,0;");//number of headers;version;items wanted (materials), set to 0 number of items,offset and length;items wanted (selected objects), set to 0 number of items,offset and length
        myStr = AddLengthToHeader(myStr);//add header
        cbData.Reason = PR_GETMEM;//reason of callback is getting data wanted size
        cbData.DataSize = 0;//we don't know actual data length
        cbData.Data = new char[(myStr.length()+1)];//allocate new memory
        sprintf(cbData.Data,"%s",myStr.c_str());//copy String to Data
        errors=callback(&cbData);//executes callback
        delete cbData.Data;//destroy previously allocated memory
        if(!errors) {
            if (cbData.DataSize > 0){//there's something to get
                try{
                    unsigned errors1;// errors returned by callback
                    cbData.Reason = PR_GETDATA;//reason of callback
                    cbData.Data = new char[cbData.DataSize+1];//allocate necessary memory
                    sprintf(cbData.Data,"%s",myStr.c_str());//copy header to let DeleD know what we want
                    errors1=callback(&cbData);//executes callback
                    if(!errors1){
                        FILE *F1;
                        F1=fopen (salva.lpstrFile, "w");//creates a new file
                        myStr.clear();
                        myStr = String(cbData.Data);//string returned by DeleD
                        //we start to write some informations
                        fprintf(F1,"DeleD Map File;\n");// (File identifier. You can use it to check if this is a DeleD Map File)
                        fprintf(F1,"Version 1.1;\n");// (Version information)
                        fprintf(F1,"no-name-yet;00FFFFFF;75;\n");// (Scene information: name, ambient RGB values, shadow intensity 
                        
                        //we get the header as a stringlist
                        StringList head=GetHeader(myStr,String(";"));
                        
                        //we divide header as to obtain a stringlist with material numbers and offset
                        StringList head1=SubdivideString(head[3],String(","));
                        
                        //offset,total length of data and number of objects
                        int offs=atoi(head[0].c_str())+atoi(head1[2].c_str())-1;
                        int tot_len=atoi(head1[3].c_str());
                        int n_materials=atoi(head1[1].c_str());
                        
                        //Get materials informations from retrieved data
                        String Materials=GetMaterials(myStr.substr(offs,offs+tot_len),n_materials);
                        
                        //Let's print to file
                        fprintf(F1,"%s",Materials.c_str());
                        
                        head1.clear();
                        
                        //we divide header as to obtain a stringlist with objects numbers and offset
                        head1=SubdivideString(head[4],String(","));
                        
                        //offset,total length of data and number of objects
                        offs=atoi(head[0].c_str())+atoi(head1[2].c_str())-1;
                        tot_len=atoi(head1[3].c_str());
                        int n_objects=atoi(head1[1].c_str());
                        
                        //Get Objects informations from retrieved Data
                        String Objects=GetObjects(myStr.substr(offs,offs+tot_len),n_objects);
                        //Let's print to file
                        fprintf(F1,"%s",Objects.c_str());
                               
                        fprintf(F1,"0;\n");//no lights exported
                        fclose(F1);
                        MessageBox(NULL,salva.lpstrFile,"DeleD selected objects have been saved to:",0);
                    }
                    else throw errors1;                        
                }
                catch(unsigned exception){
                    ErrorMessage(exception);//show error message (you can use this block to handle errors)    
                }        
            }     
        }    
        else throw errors;
    }
    catch(unsigned exception){
        ErrorMessage(exception);//show error message (you can use this block to handle errors)    
    }       
}   
    MessageBox(NULL,"DeleD C++ templates version 1.1 written by:\n Salvatore Russo.\nLot of thanks to Jeroen and Paul Jan\nfor this new improved version of DeleD!!!","Information",0);
}