/*
 * strutil.cpp by Matze Braun <MatzeBraun@gmx.de>
 *
 * Copyright (C) 2001 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 <ctype.h>

#include "util/strutil.h"
#include "util/psconst.h"

void Split(const csString& str, csArray<csString> & arr)
{
    size_t pipePos = str.FindFirst('|');
    if (pipePos == size_t(-1))
        arr.Push(str);
    else
    {
        csString first, rest;
        str.SubString(first, 0, pipePos);
        arr.Push(first);
        str.SubString(rest, pipePos+1, str.Length()-pipePos-1);
        Split(rest, arr);
    }
}

csString& GetWordNumber(const csString& str, int number, size_t *startpos)
{
    static csString erg;
    CS_ASSERT(number>0);

    size_t pos = 0;

    // If we have a startpos pointer initiate position with that start pos
    if (startpos != NULL)
        pos = *startpos;

    if (pos>=str.Length())
    {
        erg = "";
        return erg;
    }

    //Skip leading spaces
    while (pos < str.Length() && isspace(str[pos]))
        pos++;

    while (number>1 && pos < str.Length())
    {
        if (isspace(str[pos++]))
        {
            // Skip continuous spaces
            while (pos<str.Length() && isspace(str[pos]))
            {
                pos++;
            }                
            number--;
        }
    }
    size_t pos2=pos;
    
    while (pos2 < str.Length() && !isspace(str[pos2]))
    {
        pos2++;
    }        
    
    // We have found a word, though it might be at the end of the string. 
    erg.Replace(((const char*)str)+pos,pos2-pos);

    // Anyway if we have startpos update it.
    if (startpos != NULL) *startpos = pos;

    return erg;
}


WordArray::WordArray(const csString & cmd, bool ignoreQuotes) : csStringArray()
{
    size_t pos;

    pos = 0;
    while (pos < cmd.Length())
    {
        SkipSpaces(cmd, pos);
        if (pos < cmd.Length())
        {
            if(ignoreQuotes)
                pos = AddWord(cmd, pos);
            else
                pos = AddQuotedWord(cmd, pos);
        }
    }
}

void WordArray::SkipSpaces(const csString & cmd, size_t & pos)
{
    while (pos < cmd.Length()  &&  isspace(cmd.GetAt(pos)))
        pos++;
}

size_t WordArray::AddWord(const csString & cmd, size_t pos)
{
    size_t end = cmd.FindFirst(" \f\n\r\t\v", pos);
    if(end == (size_t) -1)
        end = cmd.Length();
    Push(cmd.Slice(pos, end-pos));

    return end;
}

size_t WordArray::AddQuotedWord(const csString & cmd, size_t pos)
{
    // Check if this begins with a quotation mark
    char c = cmd.GetAt(pos);
    if (c == '\'' || c== '\"')
    {
        size_t end = cmd.FindFirst(c, pos + 1);

        if(end == (size_t) -1)
            // No matching closing quotation mark so we revert to normal behaviour
            return AddWord(cmd, pos);

        // Skip out opening quotation mark
        pos++;
        Push(cmd.Slice(pos, end-pos));

        // Skip out the closing quotation mark
        return ++end;
    }
    else
        return AddWord(cmd, pos);
}

csString& WordArray::GetTail(size_t wordNum)
{
    temp2.Clear();

    for (size_t currWordNum = wordNum; currWordNum < Length(); currWordNum++)
    {
        if (currWordNum > (size_t)wordNum)
            temp2 += " ";            
        temp2 += Get(currWordNum);
    }
    return temp2;
}

void WordArray::GetTail(size_t wordNum, csString& buff)
{
    buff.Clear();

    for (size_t currWordNum = wordNum; currWordNum < Length(); currWordNum++)
    {
        if (currWordNum > (size_t)wordNum)
            buff += " ";
            
        buff += Get(currWordNum);
    }    
}


csString& WordArray::GetWords( size_t startWord, size_t endWord)
{
    temp2.Clear();

    if ( endWord > Length() )
        endWord = Length();

    if ( startWord == endWord )
        return Get(startWord);
        
    for (size_t currWordNum = startWord; currWordNum < endWord; currWordNum++)
    {
        if (currWordNum > startWord)
            temp2 += " ";
        temp2 += Get(currWordNum);
    }
    return temp2;
}

size_t WordArray::FindStr(const char *str,int start)
{
    for (size_t i=start; i<Length(); i++)
    {
        if (Get(i) == str)
            return i;
    }
    return SIZET_NOT_FOUND;
}




bool psContain(const csString& str, const csArray<csString>& strs)
{
    for (size_t i = 0; i < strs.Length(); i++)
    {
        if (strstr(str.GetDataSafe(),strs[i].GetDataSafe()))
          return true;
    }
    return false;
}

bool psSentenceContain(const csString& sentence,const csString& word)
{
    WordArray words(sentence);
    int n = 1;
    csString currentWord;

    do {
        currentWord = words[n-1];
        if (currentWord == "")
        {
            return false;
        }
        n++;
    } while (currentWord != word);
    return true;
}


char* PS_GetFileName(char* path)
{
    size_t pos = strlen(path);
    for ( ; pos>0; pos--)
    {
        if (path[pos] == '/')
        break;
    }
    
    return path+pos+1;
}

csArray<csString> psSplitt(csString& str, char delimer)
{
    csArray<csString> splitt;

    char *curr = (char*)str.GetData();
    char *next = curr;
    while (next = strchr(curr,delimer))
    {
        *next = '\0';
        splitt.Push(csString(curr));
        *next = delimer;
        curr = ++next;
    }
    splitt.Push(csString(curr));
    return splitt;
}
