#include <amsstring4/amsstring4.hpp>

namespace ams
{

//Updated convenience functions: updated for a more python style
amsarray<amsstring> splitlines(const amsstring &s)
{
    amsarray<amsstring> ret;

    int I,I1,I2;
    amsstring q;
    int mode;
    ams_chartype c;
  
    ret.resize(0);
  
    I1 = 0;
    I = 0;
    mode = 0;
    while(I<s.size())
    {
      c = s.at(I);
      if(mode==0 && c==ams_char_cr)
      {
        mode=1;
        I2 = I;
      }
      else if(mode==0 && c==ams_char_lf)
      {
        mode = 0;
        I2 = I;
        s.substring(I1,I2,&q);
        ret.push_back(q);
        I1 = I+1;
      }
      else if(mode==1 && c==ams_char_lf)
      {
        mode = 0;
        s.substring(I1,I2,&q);
        ret.push_back(q);
        I1 = I+1;
      }
      else if(mode==1)
      {
        mode = 0;
      }
  
      I = I + 1;
    }
    s.substring(I1,s.length,&q);
    ret.push_back(q);

    return ret;
}

amsarray<amsstring> split(const amsstring &s, const ams_chartype delimitchar)
{
    amsarray<amsstring> ret;
    amsstring q;
    ret.resize(0);
  
  
    int I = 0;
    int ind1;
    int ind2;
    //int cs;
    ind1 = 0;
    ams_chartype c;
    while(I<s.length)
    {
      c = s.cstring[I];
      //cs = 0;
      if(c==delimitchar)
      {
        ind2 = I;
        ind2 = max<int>(0,ind2);
        s.substring(ind1,ind2,&q);
        ret.push_back(q);
        ind1 = I+1;
        ind2 = I+1;
        ind1 = min<int>(s.length,ind1);
        ind2 = min<int>(s.length,ind2);
      }
  
      I = I + 1;
    }
    if(ind1<s.length&&s.cstring[ind1]!=delimitchar)
    {
      s.substring(ind1,s.length,&q);
      ret.push_back(q);
    }

    return ret;
}

static int amsstring_strlen(const ams_chartype *c)
{
  int I;
  if(c!=NULL)
  {
    I = 0;
    while(c[I]!='\0')
    {
      I++;
    }
    return I;
    //return strlen((const char*) c);
  }
  else
    return 0;
}

amsarray<amsstring> split(const amsstring &s, const ams_chartype *delimitstr)
{
    amsarray<amsstring> ret;

    amsstring q;
    int I;
    int ind1,ind2;
    int cs;
    int cnt;
    ams_chartype c;
    int N = amsstring_strlen(delimitstr);
    
    if(delimitstr!=NULL)
    {
      if(N>0)
      {
        ret.resize(0);
  
        ind1 = 0;
        I = 0;
        cs = 0;
        cnt = 0;
        while(I<s.size())
        {
          c = s.at(I);
          if(cs==0 && c==delimitstr[cnt])
          {
            cs=1;
            ind2 = I;
            cnt = cnt+1;
          }
          else if(cs==1 && c==delimitstr[cnt])
          {
            cs=1;
            cnt = cnt+1;
          }
          else if(cs==1 && c!=delimitstr[cnt])
          {
            cs = 0;
            ind2 = ind1;
            cnt = 0;
            I = I - 1; //step back so you can evaluate this char again
          }
  
          if(cnt>=N)
          {
            //cut string from (ind1,ind2)
            cs = 0;
  
            ind1 = min<int>(ind1,s.size());
            ind1 = max<int>(ind1,0);
            ind2 = min<int>(ind2,s.size());
            ind2 = max<int>(ind2,0);
            ind2 = max<int>(ind2,ind1);
  
            s.substring(ind1,ind2,&q);
            ret.push_back(q);
            
            ind1 = I + 1;
            ind2 = I + 1;
            cnt = 0;
          }
          I = I + 1;
        }
  
        if(ind1<s.size())
        {
          s.substring(ind1,s.size(),&q);
          ret.push_back(q);
        }
      } //N>0
      else
      {
        ret.push_back(s);
      }
    } //ret!=NULL

    return ret;
}

//splits into two guaranteed pieces
//if a delimitchar or delimitstr is not encountered, the first piece will contain the entire string and the second will be ""
amsarray<amsstring> splitfirst(const amsstring &s, const ams_chartype delimitchar)
{
    amsarray<amsstring> ret;
    int ind;

    ret.resize(2);
    ind = s.find(delimitchar);
    if(ind>=0)
    {
        ret[0] = s.substring(0,ind);
        ret[1] = s.substring(ind+1,s.length);
    }
    else
    {
        ret[0] = s;
        ret[1] = "";
    }

    return ret;
}

amsarray<amsstring> splitfirst(const amsstring &s, const ams_chartype *delimitstr)
{
    amsarray<amsstring> ret;
    int ind;

    ret.resize(2);

    ind = s.find(delimitstr);
    if(ind>=0)
    {
        ret[0] = s.substring(0,ind);
        ret[1] = s.substring(ind+amsstring_strlen(delimitstr),s.length);
    }
    else
    {
        ret[0] = s;
        ret[1] = "";
    }

    return ret;
}

//splits a string, not counting whitespaces between non-whitespace characters
amsarray<amsstring> splitwhitespace(const amsstring &s)
{
    amsarray<amsstring> ret;

    int I;
    int mode;
    ams_chartype c;
    int ind1 = 0;
    int ind2 = 0;
    I = 0;
    mode = 0;
    amsstring q;
    bool qf = 0;
  
    ret.resize(0);
    while(qf==0)
    {
        c = s.cstring[I];
        if(!(isspace(c)||c==' '||c=='\t')&&mode==0)
        {
            mode = 1;
            ind1 = I;
            ind1 = ams::max<int>(0,ind1);
        }
        if((isspace(c)||c==' '||c=='\t'||c=='\0')&&mode==1)
        {
            mode = 0;
            ind2 = I;
            ind2 = ams::min<int>(ind2,s.length);
            s.substring(ind1,ind2,&q);
            //printf("debug: %d, %s\n",I,q.cstring);
            ret.push_back(q);
        }
        if(I>=s.length)
        {
            qf = 1;
        }

        I = I + 1;
    }

    return ret;
}

amsstring stripwhitespace(const amsstring &s)
{
    amsstring ret;

    int I;
    int ind1;
    int ind2;
    ams_chartype c;
  
    ind1 = 0;
    ind2 = 0;
    for(I=0;I<s.length;I++)
    {
        c = s.cstring[I];
        if(!(isspace(c)||c==' '||c=='\t'))
        {
            ind1 = I;
            break;
        }
        }
        for(I=s.length-1;I>=0;I--)
        {
        c = s.cstring[I];
        if(!(isspace(c)||c==' '||c=='\t'))
        {
            ind2 = I+1;
            break;
        }
    }

    ind1 = min<int>(ind1,s.size());
    ind1 = max<int>(ind1,0);
    ind2 = min<int>(ind2,s.size());
    ind2 = max<int>(ind2,0);
    ind2 = max<int>(ind1,ind2);
  
    ret = s.substring(ind1,ind2);

    return ret;
}

amsstring stripallwhitespace(const amsstring &s)
{
    amsstring ret;

    ret.resize(s.length);
    //int count;
    int I;
    int J;
    J = 0;
    ams_chartype c;
    for(I=0;I<s.length;I++)
    {
      c = s.cstring[I];
      if(!(isspace(c)||c==' '||c=='\t'||c=='\n'||c=='\r'||c=='\f'||c=='\v'||(int)c==9||(int)c==10||(int)c==11||(int)c==12))
      {
        ret.cstring[J] = s.cstring[I];
        J = J + 1;
      }
    }
    ret.resize(J);
    ret.cstring[ret.length]='\0';

    return ret;
}

//splits into two guaranteed pieces
//if an extension separator . is not encountered, the first piece will contain the entire string, the second ""
amsarray<amsstring> splitext(const amsstring &s)
{
    amsarray<amsstring> ret;
    ret.resize(2);

    int ind;
    
    ind = s.findright('.');
    if(ind<0)
    {
        ret[0] = s;
        ret[1] = "";
    }
    else
    {
        ret[0] = s.substring(0,ind);
        ret[1] = s.substring(ind,s.length);
    }
    
    return ret;
}

//splits into two guaranteed pieces
//if a path separator is not encountered, the second piece will contain the entire string, and the first ""
amsarray<amsstring> splitpath(const amsstring &s)
{
    amsarray<amsstring> ret;
    ret.resize(2);
    int ind1,ind2;

    ind1 = s.find('/');
    ind2 = s.find('\\');
    if(ind1>=0)
    {
        if(ind1==0)
        {
            ret[0] = "/";
        }
        else
        {
            ret[0] = s.substring(0,ind1);
        }
        ret[1] = s.substring(ind1+1,s.length);
    }
    else if(ind2>=0)
    {
        ret[0] = s.substring(0,ind2);
        ret[1] = s.substring(ind2+1,s.length);
    }
    else
    {
        ret[0] = "";
        ret[1] = s;
    }
    

    return ret;
}

//selects between the outermost set of delimitleft and delimitright chars
amsstring select_between(const amsstring &s, const ams_chartype delimitleft, const ams_chartype delimitright)
{
    amsstring ret;

    int ind1,ind2;

    ind1 = s.find(delimitleft);
    ind2 = s.findright(delimitright);

    if(ind1<0) ind1=0;
    if(ind2<0) ind2=s.length;

    ret = s.substring(ind1,ind2);

    return ret;
}

amsstring concatenate(const amsarray<amsstring> &slist)
{
    amsstring ret;

    int I;
    ret.resize(0);
    for(I=0;I<slist.length;I++)
    {
        ret.append(slist[I]);
    }

    return ret;
}

};//end namespace ams