/*
 * Author: Andrew Mann
 *
 * Copyright (C) 2004 PlaneShift Team (info@planeshift.it,
 * http://www.planeshift.it)
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation (version 2 of the License)
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 */


#include <psconfig.h>

#include "ivideo/material.h"
#include "ivideo/shader/shader.h"


#include "paws/pawsmanager.h"
#include "paws/pawsbutton.h"
#include "paws/pawstextbox.h"
#include "paws/pawslistbox.h"

#include "pv_resmgr.h"

#include "gui_pslist.h"
#include "partview.h"
#include "gui_material.h"




guiMaterialList::guiMaterialList(PawsManager* manager )
            :pawsWidget( manager )
{
    resource_manager=NULL;
    listbox_materialnames=NULL;
    button_close=NULL;
    button_loadlibrary=NULL;
    window_filenav=NULL;
    load_outstanding=false;
}

guiMaterialList::~guiMaterialList()
{
}



bool guiMaterialList::PostSetup()
{
    listbox_materialnames=(pawsListBox *)FindWidget("materiallist_namelist");
    button_close=(pawsButton *)FindWidget("materiallist_close_button");
    textbox_description=(pawsMultiLineTextBox *)FindWidget("materiallist_properties_textbox");
    button_loadlibrary=(pawsButton *)FindWidget("materiallist_load_library_button");

    if (windowManager->LoadWidget("data/gui/filenavigation.xml"))
    {
        window_filenav=(pawsFileNavigation *)windowManager->FindWidget("filenavigation");
        if (window_filenav)
        {
            window_filenav->Hide();
            window_filenav->SetActionButtonText("Load");
            window_filenav->SetName("MaterialListFileNav");
            window_filenav->MoveTo(200,50);
        }
    }

    return true;
}

bool guiMaterialList::OnButtonPressed(int mouseButton, int keyModifier, pawsWidget* widget)
{
    if (!widget)
        return false;
    if (widget == button_close)
        Hide();
    if (widget == button_loadlibrary)
    {
        if (window_filenav)
        {
            window_filenav->FillFileList();
            window_filenav->Show();
            load_outstanding=true;
        }
    }

    return true;
}

void guiMaterialList::OnListAction( pawsListBox* selected, int status )
{
    if (!selected)
        return;
    if (selected == listbox_materialnames)
    {
        if (status == LISTBOX_HIGHLIGHTED)
            DescribeMaterial(GetSelectedMaterial());
    }


}


bool guiMaterialList::UpdateMaterialList()
{
    int i,l;
    if (!resource_manager)
    {
        if (!PartViewApp::g_pApp || !PartViewApp::g_pApp->GetResourceManager())
            return false;
        resource_manager=PartViewApp::g_pApp->GetResourceManager();
    }
    if (!listbox_materialnames)
        return false;

    l=resource_manager->Material_GetMaterialCount();

    listbox_materialnames->Clear();

    for (i=0;i<l;i++)
    {
        pawsListBoxRow *matrow;
        pawsTextBox *column_name;
        iObject *matwrap_obj;
        const char *mat_name;
        PVMaterialTracker *tracker=resource_manager->Material_GetMaterialTracker(i);

        if (!tracker)
            continue;
        if (!tracker->material_wrapper)
            continue;
        matwrap_obj=tracker->material_wrapper->QueryObject();
        if (!matwrap_obj)
            continue;
        mat_name=matwrap_obj->GetName();
        if (!mat_name)
            continue;
        matrow=listbox_materialnames->NewRow();
        if (!matrow)
            continue;
        column_name=(pawsTextBox *)matrow->GetColumn(0);
        if (!column_name)
            continue;
        column_name->SetText(mat_name);
    }
    return true;
}

PVMaterialTracker *guiMaterialList::GetSelectedMaterial()
{
    int i;
    PVMaterialTracker *selected_mat;
    if (!resource_manager)
    {
        if (!PartViewApp::g_pApp || !PartViewApp::g_pApp->GetResourceManager())
            return false;
        resource_manager=PartViewApp::g_pApp->GetResourceManager();
    }
    if (!listbox_materialnames)
        return false;

    i=listbox_materialnames->GetSelectedRowNum();

    selected_mat=resource_manager->Material_GetMaterialTracker(i);
    return selected_mat;
}


bool guiMaterialList::DescribeMaterial(PVMaterialTracker *material_tracker)
{
    csString mat_desc_str;
    char format_buffer[256];
    iMaterial *material;
    iObject *mat_wrap_obj;
    iShader *mat_shader;
    if (!textbox_description)
        return false;
    if (!material_tracker || !material_tracker->material_wrapper)
        return false;

    mat_wrap_obj=material_tracker->material_wrapper->QueryObject();
    material=material_tracker->material_wrapper->GetMaterial();
    if (!mat_wrap_obj || !material)
        return false;

    snprintf(format_buffer,256,"Name: %s",mat_wrap_obj->GetName());
    format_buffer[255]=0x00;
    mat_desc_str.Append(format_buffer);

    float diffuse,ambient,reflective;
    material->GetReflection(diffuse,ambient,reflective);
    snprintf(format_buffer,256,"\nDiffuse: %.4f Ambient %.4f Reflection %.4f",diffuse,ambient,reflective);
    format_buffer[255]=0x00;
    mat_desc_str.Append(format_buffer);

    // Query the default shader
    csRef<iStringSet> strings = CS_QUERY_REGISTRY_TAG_INTERFACE (PartViewApp::g_pApp->object_reg, "crystalspace.shared.stringset", iStringSet);
    if (strings)
    {
        mat_shader=material->GetShader(strings->Request ("OR compatibility"));
        if (!mat_shader)
        {
            snprintf(format_buffer,256,"\nThere is no shader defined for 'OR compatibility' for this material."
                                       "\nObjects using this material may not render.");
        }
        else
        {
            const char *shader_name=mat_shader->QueryObject ()->GetName();
            if (!shader_name)
                snprintf(format_buffer,256,"\nThere is a shader defined for this material, however it has no name.");
            else
                snprintf(format_buffer,256,"\nThere is a shader defined for this material:\n  %s\nDefined Shader Variables:",shader_name);
        }
        format_buffer[255]=0x00;
        mat_desc_str.Append(format_buffer);

        if (mat_shader)
        {
            // In order to get the name of all shader variables defined in this material we have to use a 
            // roundabout method of getting the material to push them onto a stack we create and then reading
            // the stack
            csShaderVarStack varstack;
            int vs_i,vs_l;
            mat_shader->PushVariables(varstack);
            if (varstack.Length() > 0)
            {
                vs_l=varstack[0].Length();
                for (vs_i=0;vs_i<vs_l;vs_i++)
                {
                    if (varstack[0][vs_i]->Name)
                    {
                        snprintf(format_buffer,256,"\n  %s",varstack[0][vs_i]->Name);
                        format_buffer[255]=0x00;
                        mat_desc_str.Append(format_buffer);
                    }
                }
            }
            else
                mat_desc_str.Append("\n  (none)");

        }






    }


    textbox_description->SetText(mat_desc_str);

    return true;
}


void guiMaterialList::DoTimedChecks()
{
    if (!resource_manager)
    {
        if (!PartViewApp::g_pApp || !PartViewApp::g_pApp->GetResourceManager())
            return;
        resource_manager=PartViewApp::g_pApp->GetResourceManager();
    }
    if (!listbox_materialnames)
        return;


    // Check for result
    if (load_outstanding && window_filenav)
    {
        switch(window_filenav->GetSelectionState())
        {
            case PAWSFILENAV_SELECTION_CANCEL:
                load_outstanding=false;
            break;
            case PAWSFILENAV_SELECTION_PERFORM:
            {
                const char *file,*path;

                // TODO:  Check for existing files and warn
                path=window_filenav->GetCurrentPath();
                file=window_filenav->GetFullPathFilename();
                if (path && file)
                {
                    if (resource_manager->LoadLibraryFile(path,file))
                    {
                        UpdateMaterialList();
                        PartViewApp::g_pApp->pslistgui->RefreshMaterialLists();
                    }
                    else
                    {
                        // TODO: Popup a display on failure to load (false return)

                    }
                }
                load_outstanding=false;
                window_filenav->Hide();
            }
            break;
            default:
            break;
        }
    }


}







