/*
* tribe.cpp
*
* Copyright (C) 2006 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.
*
*/

#include <psconfig.h>
#include <csutil/csstring.h>

#include "tribe.h"
#include "globals.h"
#include "util/psdatabase.h"
#include "util/strutil.h"
#include "npc.h"
#include "npcclient.h"
#include "npcbehave.h"

extern iDataConnection *db;

psTribe::psTribe()
    :home_sector(0)
{
}

psTribe::~psTribe()
{
}

bool psTribe::Load(iResultRow& row)
{
    id   = row.GetInt("id");
    name = row["name"];

    home_pos = csVector3(row.GetFloat("home_x"),row.GetFloat("home_y"),row.GetFloat("home_z"));
    home_radius = row.GetFloat("home_radius");
    home_sector_name = row["home_sector_name"];

    return true;
}

bool psTribe::LoadMember(iResultRow& row)
{
    int member_id   = row.GetInt("member_id");

    members_id.Push(member_id);
    
    return true;
}

bool psTribe::CheckAttach(NPC * npc)
{
    for (size_t i=0; i < members_id.Length(); i++)
    {
        if (npc->GetID() == members_id[i])
        {
            npc->SetTribe(this);
            members.Push(npc);
            return true;
        }
    }
    for (size_t i=0; i < members.Length(); i++)
    {
        if (npc->GetName() == members[i]->GetName())
        {
            npc->SetTribe(this);
            members.Push(npc);
            db->Command("INSERT INTO tribe_members (tribe_id,member_id) "
                        "VALUES (%d,%d)",GetID(),npc->GetID());
            members_id.Push(npc->GetID());
            return true;
        }
    }
    
    return false;
}

bool psTribe::HandleDeath(NPC * npc)
{
    return false;
}

void psTribe::HandlePerception(csString perception)
{
    csArray<csString> strarr = psSplitt (perception,':');
    
    if (strarr[0] == "inventory")
    {
        AddResource(strarr[1],1);
    }
    
}

void psTribe::AddResource(csString resource, float amount)
{
    for (size_t i=0; i < resources.Length(); i++)
    {
        if (resources[i].name == resource)
        {
            resources[i].amount += amount;
            return;
        }
    }
    Resource new_res;
    new_res.name  = resource;
    new_res.amount = amount;
    resources.Push(new_res);
}


void psTribe::Advance(csTicks when,EventManager *eventmgr)
{
    for (size_t i=0; i < members.Length(); i++)
    {
        NPC *npc = members[i];
        
        Behavior * behavior = npc->GetCurrentBehavior();

        if (behavior && strcmp(behavior->GetName(),"do nothing")==0)
        {
            csString perc;
            switch (Brain(npc))
            {
            case WALK: 
                perc.Format("tribe:path%d",npcclient->GetRandom(3)+1);
                break;
            case REPRODUCE:
                perc.Format("tribe:reproduce");
                break;
            case DIG:
                perc.Format("tribe:dig");
                break;
            default:
                return; // Do nothing
            }
            
            Perception perception(perc);
            npcclient->TriggerEvent(npc,&perception);
        }
    }
}

psTribe::TribeNeed psTribe::Brain(NPC * npc)
{
    switch (npcclient->GetRandom(50)) // TODO: Replace with a brain
    {
    case 0: 
    case 1: // Double the possibility for this action.
        return WALK;
        break;
    case 2:
        // Guard to prevent to many members
        if (members.Length() < 10)    // TODO: Calculate the limit
        {
            return REPRODUCE;
        }
        break;
    case 3:
        return DIG;
        break;
    }
    return NOTHING;
}

void psTribe::GetHome(csVector3& pos, float& radius, iSector* &sector)
{ 
    pos = home_pos; 
    radius = home_radius; 
    if (home_sector == NULL)
    {
        home_sector = npcclient->GetEngine()->FindSector(home_sector_name);
    }
    sector = home_sector;
}

