/*
* pawspetitionwindow.cpp - Author: Alexander Wiseman
*
* Copyright (C) 2003 Atomic Blue (info@planeshift.it, http://www.atomicblue.org)
*
*
* 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.
*
*/
//////////////////////////////////////////////////////////////////////

// STANDARD INCLUDE
#include <psconfig.h>
#include "globals.h"

// COMMON/NET INCLUDES
#include "net/messages.h"
#include "net/msghandler.h"
#include "net/cmdhandler.h"
#include "util/strutil.h"
#include <ivideo/fontserv.h>

// PAWS INCLUDES
#include "pawspetitionwindow.h"
#include "paws/pawsprefmanager.h"
#include "paws/pawsmainwidget.h"
#include "gui/pawscontrolwindow.h"

#define CANCEL_BUTTON        1

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

pawsPetitionWindow::pawsPetitionWindow() 
    : psCmdBase( NULL,NULL,  PawsManager::GetSingleton().GetObjectRegistry() )
{
    petitionList = NULL;
    currentRow = -1;
    petText = NULL;
}

pawsPetitionWindow::~pawsPetitionWindow()
{
    /*// Unsubscribe commands and messages
    msgqueue->Unsubscribe(this, MSGTYPE_PETITION);*/
}

bool pawsPetitionWindow::PostSetup()
{
    // Setup this widget to receive messages and commands
    if ( !psCmdBase::Setup( psengine->GetMsgHandler(), psengine->GetCmdHandler()) )
        return false;

    // Subscribe to certain types of messages (those we want to handle)
    msgqueue->Subscribe(this, MSGTYPE_PETITION);

    // Subscribe certain petition commands with this widget
    cmdsource->Subscribe("/petition_list",this);

    // Grab the pointer to the petition listbox:
    petitionList  = (pawsListBox*)FindWidget("PetitionList");

    petText = (pawsMessageTextBox*)FindWidget("PetitionText");

    hasPetInterest = false;
    
    return true;
}

//////////////////////////////////////////////////////////////////////
// Command and Message Handling
//////////////////////////////////////////////////////////////////////

void pawsPetitionWindow::Show()
{
        pawsControlledWindow::Show();

        // Query the server for messages:
        hasPetInterest = true;
        QueryServer();
}

const char* pawsPetitionWindow::HandleCommand( const char* cmd )
{
    csString buff(cmd);        
    // Check which command was invoked:
    if ( buff.CompareNoCase("/petition_list") )
    {
        hasPetInterest = true;
        
        // Display this window to the user and query the server for messages at the same time
        this->Show();
    }

    return NULL;
}

void pawsPetitionWindow::HandleMessage ( MsgEntry* me )
{
    // Get the petition message data from the server
    psPetitionMessage message(me);
    if (message.msgType == PETITION_DIRTY)
    {
        if (hasPetInterest)
            QueryServer();
        return;
    }
    if (message.isGM)
        return;
    
    petitionMessage = message;

    // Check if server reported errors on the query
    if (!message.success)
    {
        psSystemMessage error(0,MSG_INFO,message.error);
        msgqueue->Publish(error.msg);
    
        petCount = 0;
        petitionList->Clear();
        petText->Clear();
        petitionList->NewRow(0);
        SetText(0, 1, PawsManager::GetSingleton().Translate("No Petitions."));
        return;
    }

    // Check no petitions:
    if (message.petitions.Length() == 0)
    {
        petCount = 0;
        petitionList->Clear();
        petText->Clear();
        petitionList->NewRow(0);
        SetText(0, 1, PawsManager::GetSingleton().Translate("No Petitions."));
        return;
    }

    // Check its type (list or confirm):
    if (message.msgType == PETITION_CANCEL)
    {
        // Check if server reported errors on the query
        if (!message.success)
        {
            psSystemMessage error(0,MSG_INFO,message.error);
            msgqueue->Publish(error.msg);
            return;
        }

        // Change the status of the position we wanted to cancel:
        if (currentRow < 0)
        {
            // This should NEVER happen (it means the server gave a bogus message)
            Error1("PetitionWindow reports invalid currentRow!");
            return;
        }

        // Remove the item and refresh the list:
        //petitionMessage.petitions.DeleteIndex(currentRow);
        AddPetitions(petitionMessage.petitions);

        psSystemMessage confirm(0,MSG_INFO,PawsManager::GetSingleton().Translate("The selected petition was cancelled."));
        msgqueue->Publish(confirm.msg);

        return;
    }

    // Update the listbox:
    AddPetitions(message.petitions);
}

void pawsPetitionWindow::Close()
{
    petitionList->Clear();
    hasPetInterest = true;
    pawsControlledWindow::Hide(); 
}

bool pawsPetitionWindow::OnButtonPressed( int mouseButton, int keyModifier, pawsWidget* widget )
{
    // We know that the calling widget is a button.
    int button = widget->GetID();

    csString widgetName( widget->GetName() );
    if ( widgetName == "New Button" )
    {
        pawsStringPromptWindow::Create(PawsManager::GetSingleton().Translate("Add Petition"), csString(""),
                                       true, 500, 60, this, "petition" );
                                       
        return true;                                       
    }
    
    switch( button )
    {
        case CANCEL_BUTTON:
        {
            if (petCount > 0)
            {
                // Get the currently selected row:
                int sel = petitionList->GetSelection();
                if (sel < 0)
                {
                    psSystemMessage error(0,MSG_INFO,PawsManager::GetSingleton().Translate("You must select a petition from the list in order to cancel it."));
                    msgqueue->Publish(error.msg);
                    return true;
                }
                
                currentRow = sel;
                
                // Send a message to the server requesting cancel
                psPetitionRequestMessage queryMsg(false, "cancel", petitionMessage.petitions.Get(currentRow).id);
                msgqueue->SendMessage(queryMsg.msg);
            }
            break;
        }
    }
    return true;
}

//////////////////////////////////////////////////////////////////////
// Helper Functions
//////////////////////////////////////////////////////////////////////

void pawsPetitionWindow::QueryServer()
{
    // Construct the special petition request message to ask the server for info
    psPetitionRequestMessage queryMsg(false, "query");
    msgqueue->SendMessage(queryMsg.msg);
}

void pawsPetitionWindow::SetText(size_t rowNum, int colNum, const char* fmt, ...)
{
    pawsListBoxRow *row = petitionList->GetRow(rowNum);
    if (!row)
    {
        return;
    }

    pawsTextBox *curCol = (pawsTextBox*)row->GetColumn(colNum);
    if (!curCol)
    {
        return;
    }

    char text[1024];
    va_list args;

    va_start(args, fmt);
    cs_vsnprintf(text,sizeof(text),fmt,args);
    va_end(args);

    // Check text overflow:
    csString overflow = text;
    if (overflow.Length() > MAX_PETITION_LENGTH)
    {
        overflow.Truncate(MAX_PETITION_LENGTH);
        overflow << "...";
    }

    curCol->SetText(overflow.GetData());
}

void pawsPetitionWindow::AddPetitions(csArray<psPetitionInfo> &petitions)
{
    // get info about the selected petition
    if (petitionList->GetRowCount() <= 0)
        petitionList->Select(NULL);
    
    if (petitionList->GetSelection() >= 0)
    {
        selectedPet.escalation = 0;
        selectedPet.player =          ((pawsTextBox*)(petitionList->GetSelected()->GetColumn(PCOL_GM)))->GetText();
        selectedPet.status =          ((pawsTextBox*)(petitionList->GetSelected()->GetColumn(PCOL_STATUS)))->GetText();
        selectedPet.created =         ((pawsTextBox*)(petitionList->GetSelected()->GetColumn(PCOL_CREATED)))->GetText();
        selectedPet.petition =        ((pawsTextBox*)(petitionList->GetSelected()->GetColumn(PCOL_PETITION)))->GetText();
    }
    else
    {
        selectedPet.escalation = -1;
    }
    petitionList->Select(NULL);
    
    // Clear the list box and add the user's petitions
    petitionList->Clear();
    petText->Clear();

    psPetitionInfo info;
    petCount = 0;
    for (size_t i = 0; i < petitions.Length(); i++)
    {
        info = petitions.Get(i);
        petCount++;
        
        // Set the data for this row:
        petitionList->NewRow(i);
        SetText(i, PCOL_GM, "%s", info.assignedgm.GetData());
        SetText(i, PCOL_STATUS, "%s", info.status.GetData());
        SetText(i, PCOL_CREATED, "%s", info.created.GetData());
        SetText(i, PCOL_PETITION, "%s", info.petition.GetData());

        // reselect the petition        
        if (selectedPet.escalation != -1)
        {
            if (selectedPet.created == info.created)
            {
                petitionList->Select(petitionList->GetRow(i));
            }
        }
    }
    // make absolutely sure that there are petitions
    if (petCount <= 0)
    {
        petitionList->NewRow(0);
        SetText(0, 1, PawsManager::GetSingleton().Translate("No Petitions"));
    }
}

void pawsPetitionWindow::OnListAction( pawsListBox* selected, int status )
{
    if (status == LISTBOX_HIGHLIGHTED)
    {
        size_t sel = petitionList->GetSelection();
        if (sel >= petitionMessage.petitions.Length())
            return;
        petText->Clear();
        petText->AddMessage(petitionMessage.petitions.Get(sel).petition);
    }
}

void pawsPetitionWindow::OnStringEntered(const char *name,int param,const char *value)
{
    if (value && strlen(value)>0)
    {
        csString command;
        command.Format("/petition %s", value );
        command.Collapse();
        psengine->GetCmdHandler()->Execute(command);
    }                
}                                        
