#include <amsstring4/amsstring4.hpp>

namespace ams
{

    void amsstring4_basic_string_test1()
    {
        char q1,c;
        unsigned char q2;
        uint8_t q3;
        int I;
    
        printf("Basic string tests1.\n");
        for(I=-127;I<256;I++)
        {
            c = (char)I;
            q2 = (unsigned char) I;
            //printf("I=%d  %d %c %02x %02x %02x\n",I,(int)c,c,c,(unsigned char)c,I);
            printf("I=%d, %c, %02x\n",I,q2,q2);
        }
    
        q2 = (unsigned char) '\r';
        printf("\nLF: %c After LF %c After LF2 \n",q2,q2);
    }
    
    void amsstring4_sscanf_test1()
    {
        char buf[500];
        double d;
        int q;
        
        // //vsnprintf(buf,500," -123.456E10 ");
        // snprintf(buf,500," -123.456E10 ");
        // //sprintf_s(buf,500," -123.456E10 ");
        // q=sscanf(buf,"%lf",&d);
        // printf("Buffer %s reads as %1.4g, q=%d\n",buf,d,q);
    
        // snprintf(buf,500," -inf ");
        // //sprintf_s(buf,500," -123.456E10 ");
        // q=sscanf(buf,"%lf",&d);
        // printf("Buffer %s reads as %1.4g, q=%d\n",buf,d,q);
    
        // snprintf(buf,500,"3");
        // //sprintf_s(buf,500," -123.456E10 ");
        // q=sscanf(buf,"%lf",&d);
        // printf("Buffer %s reads as %1.4g, q=%d\n",buf,d,q);
    
        // snprintf(buf,500," #.QUAN0 ");
        // //sprintf_s(buf,500," -123.456E10 ");
        // q=sscanf(buf,"%lf",&d);
        // printf("Buffer %s reads as %1.4g, q=%d\n",buf,d,q);
    
        // snprintf(buf,500,"nan");
        // //sprintf_s(buf,500," -123.456E10 ");
        // q=sscanf(buf,"%lf",&d);
        // printf("Buffer %s reads as %1.4g, q=%d\n",buf,d,q);
    
        amssprintf_s(buf,500,"-3");
        d = amsstrtonum(buf);
        printf("String %s reads as %1.4g\n",buf,d);
    
        amssprintf_s(buf,500,"   -3  ");
        d = amsstrtonum(buf);
        printf("String %s reads as %1.4g\n",buf,d);
    
        amssprintf_s(buf,500,"\t\t-3\t\n  ");
        d = amsstrtonum(buf);
        printf("String %s reads as %1.4g\n",buf,d);
    
        amssprintf_s(buf,500,"   +3E+1  ");
        d = amsstrtonum(buf);
        printf("String %s reads as %1.4g\n",buf,d);
    
        amssprintf_s(buf,500,"2,3,4");
        d = amsstrtonum(buf);
        printf("String %s reads as %1.4g\n",buf,d);
    
        amssprintf_s(buf,500,"inf");
        d = amsstrtonum(buf);
        printf("String %s reads as %1.4g\n",buf,d);
    
        amssprintf_s(buf,500,"-inf");
        d = amsstrtonum(buf);
        printf("String %s reads as %1.4g\n",buf,d);
    
        amssprintf_s(buf,500,"nan");
        d = amsstrtonum(buf);
        printf("String %s reads as %1.4g\n",buf,d);
    
        amssprintf_s(buf,500,"1.0*4E3");
        d = amsstrtonum(buf);
        printf("String %s reads as %1.4g\n",buf,d);
    
        amssprintf_s(buf,2,"2,3,4");
        d = amsstrtonum(buf);
        printf("String %s reads as %1.4g\n",buf,d);
    
        amssprintf_s(buf,2,NULL);
        d = amsstrtonum(buf);
        printf("String %s reads as %1.4g\n",buf,d);
    
        amssprintf_s(NULL,2,"100");
        d = amsstrtonum(buf);
        printf("String %s reads as %1.4g\n",buf,d);
    }
    
    void amsstring4_basic_string_test2()
    {
        amsstring s1,s2;
        //const amsstring s3; //don't do this - just accept that strings must be mutable
    
        s1="Hello world";
        s2 = s1;
        printf("%d %c\n",(ams_chartype) '\0', (ams_chartype) '\0');
        printf("s1: '%s', s2: '%s'\n",s1.cstring,s2.cstring);
        int I;
        for(I=-5;I<s2.size()+5;I++)
        {
            printf("s2[%d]: %d, %c \n",I,s2[I],s2[I]);
        }
    
        for(I=-5;I<s2.size()+5;I++)
        {
            s1[I] = 'a';
        };
        printf("s1 = %s\n",s1.cstring);
        for(I=-5;I<s2.size()+5;I++)
        {
            printf("s1[%d]: %d, %c \n",I,s1[I],s1[I]);
        }
    
        printf("s1:'%s'==s2:'%s'?:%d\n",s1.cstring,s2.cstring,s1==s2);
        s1 = "Hello";
        s2 = "Hello";
        printf("s1:'%s'==s2:'%s'?:%d\n",s1.cstring,s2.cstring,s1==s2);
        s2.resize(15);
        s2[10] = 'b';
        //s2[5] = 'b';
        //s2[6] = 'b';
        printf("s1.size()=%d, s2.size()=%d\n",s1.size(),s2.size());
        printf("s1:'%s'==s2:'%s'?:%d\n",s1.cstring,s2.cstring,s1==s2);
        s2[10] = 'a';
        s2.shrinktofit();
        printf("s1.size()=%d, s2.size()=%d\n",s1.size(),s2.size());
        printf("s1:'%s'==s2:'%s'?:%d\n",s1.cstring,s2.cstring,s1==s2);
        
        s1 = "hello"; s2 = "Hello";
        printf("s1:'%s'>s2:'%s'?:%d\n",s1.cstring,s2.cstring,s1>s2);
        s1 = "hello"; s2 = "Hello";
        printf("s1:'%s'<s2:'%s'?:%d\n",s1.cstring,s2.cstring,s1<s2);
        s1 = "Hello"; s2 = "Hello";
        printf("s1:'%s'>s2:'%s'?:%d\n",s1.cstring,s2.cstring,s1>s2);
        
        //s3 = "Hello constant world.";
        //printf("s3= '%s'\n",s3.cstring);
    
    }
    
    void amsstring4_memoryleakcheck1()
    {
        amsstring q1,q2,q3;
        int I;
    
        q1.sprintf(1000,"%1.100g,",ams::pi);
        printf("q1='%s'\n",q1.cstring);
        printf("q1.size()=%d\n",q1.size());
        q2 = q1;
        for(I=0;I<100;I++)
        {
            q1.substring(0,q1.length-1,&q1);
            printf("q1 = substr; q1='%s'\n",q1.cstring);
        }
    
        q1 = q2;
        q1.resize(10000000);
        for(I=0;I<20;I++)
        {
            printf("resize test %d\n",(int)I);
            q2 = q1;
            q2.resize(10000000);
            q3 = q2;
            q3.resize(10000000);
            q1 = q3;
            q1.resize(10000000);
        }
        return;
    }
    
    void amsstring4_memoryleakcheck2()
    {
        int I;
        amsstring q1;
    
        for(I=0;I<100;I++)
        {
            q1.sprintf(4,"%1.100g",ams::pi);
        }
        printf("q1=%s\n",q1.cstring);
    }
    
    void amsstring4_stringtests2()
    {
        amsstring q1,q2;
        int I;
        amsarray<amsstring> qarr;
    
        q1.insert(0,"Hello world");
        printf("q1='%s'\n",q1.cstring);
    
        for(I=-2;I<15;I++)
        {
            q2 = q1;
            q2.insert(I,"<insert>");
            printf("q2=q1;q2.insert(%d,'<insert'>) = '%s' size=%d\n",I,q2.cstring,q2.size());
        }
    
        q1 = "Hello world.";
        for(I=-5;I<15;I++)
        {
            q2 = q1;
            q2.remove(I);
            printf("q2.remove(%d) = '%s'\n",I,q2.cstring);
        }
    
        for(I=-5;I<15;I++)
        {
            q2 = q1;
            q2.remove(I,I+2);
            printf("q2.remove(%d,%d) = '%s'\n",I,I+2,q2.cstring);
        }
    
        q1 = "Hello hEllo 1,2,3;";
        printf("q1='%s'\n",q1.cstring);
        q1.tolower();
        printf("q1='%s'\n",q1.cstring);
        q1.toupper();
        printf("q1='%s'\n",q1.cstring);
        
        q1.append("hello more appened stuff...");
        printf("q1='%s'\n",q1.cstring);
        
        q1.substring(-5,5,&q1);
        printf("q1='%s'\n",q1.cstring);
        
        q1 = "Hello 1,2,3";
        printf("q1='%s', q1.isvalidnumber() = %d, q1.strtonum=%1.6g\n",q1.cstring,q1.isvalidnumber(),q1.strtonum());
        q1 = "   3.1415   ";
        printf("q1='%s', q1.isvalidnumber() = %d, q1.strtonum=%1.6g\n",q1.cstring,q1.isvalidnumber(),q1.strtonum());
        q1 = "-inf";
        printf("q1='%s', q1.isvalidnumber() = %d, q1.strtonum=%1.6g\n",q1.cstring,q1.isvalidnumber(),q1.strtonum());
        q1 = "nan";
        printf("q1='%s', q1.isvalidnumber() = %d, q1.strtonum=%1.6g\n",q1.cstring,q1.isvalidnumber(),q1.strtonum());
        q1 = "1.1E1,2.2E2";
        printf("q1='%s', q1.isvalidnumber() = %d, q1.strtonum=%1.6g\n",q1.cstring,q1.isvalidnumber(),q1.strtonum());
        q1 = ",1,2,3";
        printf("q1='%s', q1.isvalidnumber() = %d, q1.strtonum=%1.6g\n",q1.cstring,q1.isvalidnumber(),q1.strtonum());
        
        // qarr.resize(1000);
        // for(I=0;I<1000;I++)
        // {
        //     qarr[I].sprintf(1000,"%1.500g\n",ams::pi);
        //     qarr[I].resize(1000000);
        // }
        // printf("%d",qarr[0].size());
        q1 = "Hello world";
        for(I=-2;I<15;I++)
        {
            q1.substring(I,I+3,&q2);
            printf("q1[%d:%d] = '%s' size=%d\n",I,I+3,q2.cstring,q2.size());
        }
    
        return;
    }
    
    void amsstring4_test_find()
    {
        amsstring q1,q2,q3;
        int I;
    
        q1 = "hello world";
        q3 = "<inser";
        printf("q3='%s'\n",q3.cstring);
        for(I=-1;I<13;I++)
        {
            q2 = q1;
            q2.insert(I,"<insert>");
            printf("q2=q1;q2.insert(%d,'<insert'>) = '%s' q2.find(q3)=%d\n",I,q2.cstring,q2.find(q3,0,0));
        }
    
        q3 = "<inSeRt>";
        printf("\nq3='%s'\n",q3.cstring);
        for(I=-1;I<13;I++)
        {
            q2 = q1;
            q2.insert(I,"<insert>");
            printf("q2=q1;q2.insert(%d,'<insert'>) = '%s' q2.find(q3)=%d\n",I,q2.cstring,q2.find(q3,0,0));
        }
    
        q3 = "<insert> ";
        printf("\nq3='%s'\n",q3.cstring);
        for(I=-1;I<13;I++)
        {
            q2 = q1;
            q2.insert(I,"<insert>");
            printf("q2=q1;q2.insert(%d,'<insert'>) = '%s' q2.find(q3)=%d\n",I,q2.cstring,q2.find(q3,0,0));
        }
    
        return;
    }
    
    void amsstring4_test_splitlines()
    {
        int I;
        amsstring q1;
        amsarray<amsstring> lns;
        q1 = "This is a \n string on \n multiple \r\n lines\n\n with CR\\LFs\n";
        //q1 = "\n\n";
        //q1 = "";
        //q1 = "More malformed\r string nonsense\n\r\n\r\r\na";
    
        printf("q1='%s'\n",q1.cstring);
        splitlines(&q1,&lns);
        for(I=0;I<lns.size();I++)
        {
            printf("Line %d: '%s'\n",I,lns[I].cstring);
        }
        return;
    }
    
    void amsstring4_test_split()
    {
        amsstring q1;
        amsarray<amsstring> strs;
        int I;
    
        q1 = "this is a string  to split  ";
        printf("string='%s'\n",q1.cstring);
        split(&q1," ",&strs);
        for(I=0;I<strs.size();I++)
        {
            printf("S[%d]: '%s'\n",I,strs[I].cstring);
        }
    
        q1 = "A\tbunch of tab\tseparated \tvariables\t";
        printf("string='%s'\n",q1.cstring);
        split(&q1,"\t",&strs);
        for(I=0;I<strs.size();I++)
        {
            printf("S[%d]: '%s'\n",I,strs[I].cstring);
        }
    
        q1 = "Delimiter is abcd, a ab abcd qabcqdqabcdq";
        printf("string='%s'\n",q1.cstring);
        split(&q1,"abcd",&strs);
        for(I=0;I<strs.size();I++)
        {
            printf("S[%d]: '%s'\n",I,strs[I].cstring);
        }
    
        q1 = "abc";
        printf("string='%s'\n",q1.cstring);
        split(&q1,"abcd",&strs);
        for(I=0;I<strs.size();I++)
        {
            printf("S[%d]: '%s'\n",I,strs[I].cstring);
        }
    
        q1 = "";
        printf("string='%s'\n",q1.cstring);
        split(&q1,"abcd",&strs);
        for(I=0;I<strs.size();I++)
        {
            printf("S[%d]: '%s'\n",I,strs[I].cstring);
        }
    
        q1 = "A string not to split.";
        printf("string='%s'\n",q1.cstring);
        split(&q1,"",&strs);
        for(I=0;I<strs.size();I++)
        {
            printf("S[%d]: '%s'\n",I,strs[I].cstring);
        }
    
        q1 = "A  string to  split\tby\t \twhitespace";
        printf("string='%s'\n",q1.cstring);
        splitwhitespace(&q1,&strs);
        for(I=0;I<strs.size();I++)
        {
            printf("S[%d]: '%s'\n",I,strs[I].cstring);
        }
    
        return;
    }
    
    void amsstring4_test_strip()
    {
        amsstring q1;
        amsarray<amsstring> strs;
        int I;
    
        q1 = "   ";
        printf("string ws  ='%s'\n",q1.cstring);
        stripwhitespace(&q1);
        printf("string nows='%s'\n",q1.cstring);
        
        q1 = "\t  something = something else\t ";
        printf("string ws  ='%s'\n",q1.cstring);
        stripwhitespace(&q1);
        printf("string nows='%s'\n",q1.cstring);
        
        stripwhitespace(NULL);
    
        q1 = "\t  something = something else\t ";
        printf("string ws   ='%s'\n",q1.cstring);
        stripallwhitespace(&q1);
        printf("string allws='%s'\n",q1.cstring);
    
        return;
    }
    
    void amsstring4_test_freadwrite()
    {
        FILE *fp = NULL;
        FILE *fp2 = NULL;
        int I;
        amsstring q;
        amsarray<amsstring> q2;
    
        fp = fopen("./ref/0p375_hexbolt.scad","r");
        fp2 = fopen("./ref/testrewrite.scad","w+");

        if(fp==NULL || fp2==NULL)
        {
            printf("amsstring4_test_freadwrite: could not open test files, make sure you're executing this from the project root.\n");
            return;
        }
    
        I = 0;
        while(!feof(fp))
        {
            freadline(fp,&q);
            printf("Line %d: '%s'\n",I,q.cstring);
            I = I + 1;
        }
    
        fseek(fp,SEEK_SET,0);    
    
        freadlines(fp,&q2);
        for(I=0;I<q2.size();I++)
        {
            printf("Line %d: '%s'\n",I,q2[I].cstring);
        }
    
        //q = "This is a test file\nto write\n\thello\n\n";
        //fwritelines(fp2,&q);
    
        fwritelines(fp2,&q2);
    
    
        fclose(fp);
        fclose(fp2);
        return;
    }
    
    void amsstring4_test_concatenation_operators()
    {
        ams::amsstring a,b,c,d;
    
        a = "";
        a = a + "hello";
        a = a+ " world\n";
        b = a+a;
        c = b+a;
    
        printf("%s\n",b.cstring);
    
        return;
    }

};