// This file is a part of the xMule Project.
//
// Copyright (c) 2004 Theodore R. Smith (hopeseekr@xmule.ws / http://www.xmule.ws/)
// DSA-1024 Fingerprint: 10A0 6372 9092 85A2 BB7F 907B CB8B 654B E33B F1ED
//
// Copyright (C)2002 Merkur ( merkur-@users.sourceforge.net / http://www.xmule-project.net )
//
// 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; either
// version 2 of the License, or (at your option) any later version.
// 
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.

#ifdef PRECOMP
#	include "xmule-headers.h"
#else
#	include "server.h"
#	include "opcodes.h"
#	include "otherfunctions.h"
#include "packets.h"                        // CTag
#	include "xmule.h"
#endif
#include "SafeFile.h"
#include "otherstructs.h"

#include <netinet/in.h>
#include <arpa/inet.h>

#include <wx/listimpl.cpp>
WX_DEFINE_LIST(TagList);

CServer::CServer(ServerMet_Struct *in_data)
{
    //taglist = new CTypedPtrList<CPtrList, CTag*>;
    taglist = new TagList;
    port = in_data->port;
    tagcount = 0;
    ip = in_data->ip;
    in_addr host;
    host.s_addr = ip;
    strcpy(ipfull, inet_ntoa(host));
    files = 0;
    users = 0;
    preferences = 0;
    ping = 0;
    description = 0;
    listname = 0;
    dynip = 0;
    failedcount = 0;
    lastpinged = 0;
    staticservermember = 0;
    maxusers = 0;
    m_uTCPFlags = 0;
    m_uUDPFlags = 0;
}

CServer::CServer(uint16_t in_port, char *i_addr)
{
    //taglist = new CTypedPtrList<CPtrList, CTag*>;
    taglist = new TagList;
    port = in_port;
    tagcount = 0;
    if (inet_addr(i_addr) == INADDR_NONE)
    {
        dynip = strdup(i_addr);
        ip = 0;
    }
    else
    {
        ip = inet_addr(i_addr);
        dynip = 0;
    }
    in_addr host;
    host.s_addr = ip;
    strcpy(ipfull, inet_ntoa(host));
    files = 0;
    users = 0;
    preferences = 0;
    ping = 0;
    description = 0;
    listname = 0;
    failedcount = 0;
    lastpinged = 0;
    staticservermember = 0;
    maxusers = 0;
    m_uTCPFlags = 0;
    m_uUDPFlags = 0;
}

// copy constructor
CServer::CServer(CServer *pOld)
{
    //taglist = new CTypedPtrList<CPtrList, CTag*>;
    taglist = new TagList;
    //for(POSITION pos = pOld->taglist->GetHeadPosition(); pos != NULL; pOld->taglist->GetNext(pos))
    for (TagList::Node *pos = pOld->taglist->GetFirst() ; pos != NULL ; pos = pos->GetNext())
    {
        //pOld->taglist->GetAt(pos);:
        CTag *pOldTag = pos->GetData();
        //AddTail(pOldTag->CloneTag());:
        taglist->Append(pOldTag->CloneTag());
    }
    port = pOld->port;
    ip = pOld->ip;
    staticservermember = pOld->IsStaticMember();
    tagcount = pOld->tagcount;
    strcpy(ipfull, pOld->ipfull);
    files = pOld->files;
    users = pOld->users;
    preferences = pOld->preferences;
    ping = pOld->ping;
    failedcount = pOld->failedcount;
    lastpinged = pOld->lastpinged;
    if (pOld->description)
    description = nstrdup(pOld->description);
    else
    description = NULL;
    if (pOld->listname)
    listname = nstrdup(pOld->listname);
    else
    listname = NULL;
    if (pOld->dynip)
    dynip = nstrdup(pOld->dynip);
    else
    dynip = NULL;
    maxusers = pOld->maxusers;
    m_strVersion = pOld->m_strVersion;
    m_uTCPFlags = pOld->m_uTCPFlags;
    m_uUDPFlags = pOld->m_uUDPFlags;
}

CServer::~CServer()
{
    if (description)
    delete[] description;
    if (listname)
    delete[] listname;
    if (dynip)
    delete[] dynip;
    //for(POSITION pos = taglist->GetHeadPosition(); pos != NULL; taglist->GetNext(pos))
    if (taglist)
    {
        for (TagList::Node *pos = taglist->GetFirst() ; pos != NULL ; pos = pos->GetNext())
        //taglist->GetAt(pos);:
        delete pos->GetData();
        //RemoveAll();:
        taglist->Clear();
        delete taglist;
        taglist = NULL;
    }
}

bool CServer::AddTagFromFile(CSafeFile *servermet)
{
    if (servermet == 0)
    return false;
    CTag *tag = new CTag(servermet);
    switch (tag->tag->specialtag)
    {
    case ST_SERVERNAME:
        listname = nstrdup(tag->tag->stringvalue);
        delete tag;
        break;
    case ST_DESCRIPTION:
        description = nstrdup(tag->tag->stringvalue);
        delete tag;
        break;
    case ST_PREFERENCE:
        preferences = tag->tag->intvalue;
        delete tag;
        break;
    case ST_PING:
        ping = tag->tag->intvalue;
        delete tag;
        break;
    case ST_DYNIP:
        dynip = nstrdup(tag->tag->stringvalue);
        delete tag;
        break;
    case ST_FAIL:
        failedcount = tag->tag->intvalue;
        delete tag;
        break;
    case ST_LASTPING:
        lastpinged = tag->tag->intvalue;
        delete tag;
        break;
    case ST_MAXUSERS:
        maxusers = tag->tag->intvalue;
        delete tag;
        break;
    case ST_SOFTFILES:
        softfiles = tag->tag->intvalue;
        delete tag;
        break;
    case ST_HARDFILES:
        hardfiles = tag->tag->intvalue;
        delete tag;
        break;
    case ST_VERSION:
        if (tag->tag->type == 2)
        {
            m_strVersion = tag->tag->stringvalue;
        }
        delete tag;
        break;
    case ST_UDPFLAGS:
        if (tag->tag->type == 3)
        {
            m_uUDPFlags = tag->tag->intvalue;
        }
        delete tag;
        break;
    default:
        if (tag->tag->specialtag)
        {
            tag->tag->tagname = nstrdup("Unknown");
            AddTag(tag);
        }
        else if(!strcmp(tag->tag->tagname, "files"))
        {
            files = tag->tag->intvalue;
            delete tag;
        }
        else if(!strcmp(tag->tag->tagname, "users"))
        {
            users = tag->tag->intvalue;
            delete tag;
        }
        else
        AddTag(tag);
    }
    return true;
}

void CServer::SetListName(char *newname)
{
    if (listname)
    delete[] listname;
    listname = nstrdup(newname);
}

void CServer::SetDescription(char *newname)
{
    if (description)
    delete[] description;
    description = nstrdup(newname);
}

void CServer::FillWindowTags(wxTreeCtrl *wnd, wxTreeItemId rootitem)
{
#if 0
    POSITION pos;
    char buffer[255];
    if (description)
    {
        sprintf(buffer, GetResString(IDS_DESC), description);
        wnd->InsertItem(buffer, - 1, - 1, rootitem);
    }
    sprintf(buffer, GetResString(IDS_IP) + ": %s", ipfull);
    wnd->InsertItem(buffer, - 1, - 1, rootitem);
    sprintf(buffer, GetResString(IDS_PORT) + ": %i", port);
    wnd->InsertItem(buffer, - 1, - 1, rootitem);
    if (ping)
    {
        sprintf(buffer, GetResString(IDS_PING) + ": %i", ping);
        wnd->InsertItem(buffer, - 1, - 1, rootitem);
    }
    if (users)
    {
        sprintf(buffer, GetResString(IDS_USERS), users);
        wnd->InsertItem(buffer, - 1, - 1, rootitem);
    }
    if (files)
    {
        sprintf(buffer, GetResString(IDS_FILES) + ": %i", files);
        wnd->InsertItem(buffer, - 1, - 1, rootitem);
    }
    CTag *cur_tag;
    for (int i = 0 ; i != taglist->GetCount() ; i++)
    {
        pos = taglist->FindIndex(i);
        cur_tag = taglist->GetAt(pos);
        if (cur_tag->tag->specialtag)
        continue;
        if (cur_tag->tag->type == 2)
        sprintf(buffer, "%s: %s", cur_tag->tag->tagname, cur_tag->tag->stringvalue);
        else if(cur_tag->tag->type == 3)
        sprintf(buffer, "%s: %i", cur_tag->tag->tagname, cur_tag->tag->intvalue);
        else
        continue;
        wnd->InsertItem(buffer, - 1, - 1, rootitem);
    }
#endif
    printf("todo. fill window tags\n");
}

char *CServer::GetAddress()
{
    if (dynip)
    return dynip;
    else
    return ipfull;
}

void CServer::SetID(uint32_t newip)
{
    ip = newip;
    in_addr host;
    host.s_addr = ip;
    strcpy(ipfull, inet_ntoa(host));
}

void CServer::SetDynIP(char *newdynip)
{
    if (dynip)
    delete[] dynip;
    dynip = nstrdup(newdynip);
}

