/*   Copyright 2004 The Apache Software Foundation
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package misc.checkin;

import org.apache.xmlbeans.impl.store.CharUtil;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Random;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

public class CharUtilTests
{
    private static class Triple {

        Triple ( Object src, int off, int cch )
        {
            _src = src;
            _off = off;
            _cch = cch;
        }
        
        final Object _src;
        final int    _off;
        final int    _cch;
    }

    private char randomChar ( )
    {
        int n = rnd( 27 );
        
        switch ( n )
        {
            case 0  : return ' ';
            default : return (char)( 'a' + n - 1 );
        }
    }
    
    private String randomString ( )
    {
        StringBuffer sb = new StringBuffer();

        for ( int i = rnd( 128 ) ; i >= 0 ; i-- )
            sb.append( randomChar() );

        return sb.toString();
    }
            
    private interface CharUtilTest
    {
        void newText ( String s );

        int numTexts ( );

        String getText ( int i );
        
        int length ( int i );

        void insert ( int i, int j, int off );
        
        void remove ( int i, int off, int cch );
    }

    private static class RealCharUtil implements CharUtilTest
    {
        public void newText ( String s )
        {
            _triples.add( new Triple( s, 0, s.length() ) );
        }

        public int numTexts ( )
        {
            return _triples.size();
        }

        public String getText ( int i )
        {
            Triple t = (Triple) _triples.get( i );

            return CharUtil.getString( t._src, t._off, t._cch );
        }

        public int length ( int i )
        {
            return ((Triple) _triples.get( i ))._cch;
        }
        
        public void insert ( int i, int j, int off )
        {
            Triple ti = (Triple) _triples.get( i );
            Triple tj = (Triple) _triples.get( j );
            
            Object src =
                _cu.insertChars( off, ti._src, ti._off, ti._cch, tj._src, tj._off, tj._cch );

            _triples.set( i, new Triple( src, _cu._offSrc, _cu._cchSrc ) );
        }
        
        public void remove ( int i, int off, int cch )
        {
            Triple ti = (Triple) _triples.get( i );
            
            Object src = _cu.removeChars( off, cch, ti._src, ti._off, ti._cch );
            
            _triples.set( i, new Triple( src, _cu._offSrc, _cu._cchSrc ) );
        }
        
        ArrayList _triples = new ArrayList();
        CharUtil _cu = new CharUtil( 1024 );
    }
    
    private static class FakeCharUtil implements CharUtilTest
    {
        public void newText ( String s )
        {
            _strings.add( s );
        }

        public int numTexts ( )
        {
            return _strings.size();
        }

        public String getText ( int i )
        {
            return (String) _strings.get( i );
        }

        public int length ( int i )
        {
            return ((String) _strings.get( i )).length();
        }
        
        public void insert ( int i, int j, int off )
        {
            String si = (String) _strings.get( i );
            String sj = (String) _strings.get( j );

            _strings.set( i, si.substring( 0, off ) + sj + si.substring( off ) );
        }

        public void remove ( int i, int off, int cch )
        {
            String si = (String) _strings.get( i );
            
            _strings.set( i, si.substring( 0, off ) + si.substring( off + cch ) );
        }
                
        ArrayList _strings = new ArrayList();
    }

    @Test
    public void testCharUtil ( ) throws Exception
    {
        RealCharUtil real = new RealCharUtil();
        FakeCharUtil fake = new FakeCharUtil();

        for ( int iter = 0 ; iter < 5000 ; iter++ )
        {
            switch( rnd( 4 ) )
            {
            case 0 :
            {
                String s = randomString();

                real.newText( s );
                fake.newText( s );

                break;
            }

            case 1 :
            {
                assertEquals(real.numTexts(), fake.numTexts());

                if (real.numTexts() > 0)
                {
                    int j = rnd( real.numTexts() );

                    assertEquals(real.getText(j), fake.getText(j));
                }
            }
            
            case 2 :
            {
                if (real.numTexts() > 1)
                {
                    int i = rnd( real.numTexts() );
                    int j = rnd( real.numTexts() );
                    int off = rnd( real.length( i ) + 1 );

                    real.insert( i, j, off );
                    fake.insert( i, j, off );

                    assertEquals(real.getText(i), fake.getText(i));
                    assertEquals(real.getText(j), fake.getText(j));
                }
            }
            case 3 :
            {
                int i = rnd( real.numTexts() );
                int l = real.length( i );
                int off = rnd( l + 1 );
                int cch = rnd( l - off + 1 );

                real.remove( i, off, cch );
                fake.remove( i, off, cch );

                assertEquals(real.getText(i), fake.getText(i));
            }
            }
        }
    }

    private int rnd ( int n )
    {
        return n == 1 ? 0 : _rnd.nextInt( n - 1 );
    }

    private Random _rnd = new Random( 0 );

    @Test
    public void testThreadLocal() {
        assertNotNull("Should always get a CharUtil from ThreadLocals", CharUtil.getThreadLocalCharUtil());
        CharUtil.clearThreadLocals();
        assertNotNull("Should always get a CharUtil from ThreadLocals", CharUtil.getThreadLocalCharUtil());
    }
}