require 'test/unit'
require 'patman'
require 'fileutils'

# require 'byebug'


class PatmanTest < Test::Unit::TestCase

    # Test all editing features.
    def test_editing

        ifile = 'test/input/test_file1.txt'

        # Open file.
        r = Patman.read( ifile )

        # Should be at file beginning.
        assert_equal( r.line, 1 )
        assert_equal( r.edited?, false )

        # ------------------------------------------------------------
        # Test diff jumping commands and their return values:
        r.step;        assert_equal( r.line, 2 )
        r.step -1;     assert_equal( r.line, 1 )
        true;          assert_equal( r.step.line, 2 )
        true;          assert_equal( r.step(-1).line, 1 )
        r.line( 5 );   assert_equal( r.line, 5 )
        r.firstline;   assert_equal( r.line, 1 )
        r.lastline;    assert_equal( r.line, 10 )


        # ------------------------------------------------------------
        # Test searching:
        assert_equal( r.firstline.find( /Line 1/ ), true )
        assert_equal( r.firstline.find( /Line 2/ ), true )
        assert_equal( r.line( 4 ).find( /Line 3/ ), false )
        assert_equal( r.firstline.search( /Line 1/ ).line, 1 )
        assert_equal( r.search( /Line 2/ ).line, 2 )
        assert_equal( r.search( /ne 8/ ).line, 8 )
        l = r.excursion do
            r.search( /Line 9/ ).line
        end
        assert_equal( r.line, 8 )
        assert_equal( l, 9 )

        err = false
        begin
            r.search( /Line 2/ )
        rescue Patman::PatmanSearchError
            err = true
        end
        assert_equal( err, true )

        err = false
        begin
            r.search( /Line 2/, false )
        rescue Patman::PatmanSearchError
            err = true
        end
        assert_equal( err, false )
        assert_equal( r.line, 2 )

        err = false
        begin
            r.search( /Line 9/, false )
        rescue Patman::PatmanSearchError
            err = true
        end
        assert_equal( err, true )
        assert_equal( r.line, 2 )


        # ------------------------------------------------------------
        # Test content queries:
        assert_equal( r.firstline.get, "Line 1" )
        assert_equal( r.ref( 10 ), "Line 10" )
        assert_equal( r.ref( 11 ), nil )
        assert_equal( r.line, 1 )
        assert_equal( r.get_range( 1, 2 ), ["Line 1", "Line 2"] )
        assert_equal( r.get_for( 1, 2 ), ["Line 1", "Line 2"] )


        # ------------------------------------------------------------
        # Test content manipulation:
        l = r.get
        r.set( "foobar" )
        assert_equal( r.get, "foobar" )
        r.set( l )
        assert_equal( r.length, 10 )

        r.update do |c|
            c.gsub( /ne/, 'en' )
        end
        assert_equal( r.get, "Lien 1" )
        r.set( l )


        r.insert( 'Line -1' )
        assert_equal( r.length, 11 )
        assert_equal( r.get, "Line -1" )
        r.delete
        assert_equal( r.length, 10 )
        assert_equal( r.get, "Line 1" )

        c = %w{foo bar}
        r.insert( c )
        assert_equal( r.length, 12 )
        assert_equal( r.get_range( 1, 2 ), c )
        assert_equal( r.delete(2).length, 10 )

        assert_equal( r.lastline.append( 'foo' ).get, 'foo' )
        assert_equal( r.append( 'bar' ).get, 'bar' )
        assert_equal( r.length, 12 )
        assert_equal( r.get_range(11,12), c )
        assert_equal( r.line, r.length )
        assert_equal( r.append( %w{foo bar} ).length, 14 )
        assert_equal( r.get_range(13,14), c )
        r.line( 11 ).delete( 4 )

        len = r.length
        assert_equal( r.firstline.insertfile( ifile ).length, 2*len )
        assert_equal( r.lastline.step.insertfile( ifile ).length, 3*len )

        r.do_all do |r|
            r.sub( /Line/, 'foobar' )
        end
        assert_equal( r.get_range(5,6), [ 'foobar 5', 'foobar 6' ] )
        r.blockline
        assert_equal( r.line, 30 )

        r.do_range( 1, r.length-1 ) do |r|
            r.sub( /foobar/, 'Line' )
        end
        assert_equal( r.get_range(5,6), [ 'Line 5', 'Line 6' ] )

        r.do_for( 1, r.length-1 ) do |r|
            r.sub( /Line/, 'foobar' )
        end
        assert_equal( r.get_range(5,6), [ 'foobar 5', 'foobar 6' ] )


        # ------------------------------------------------------------
        # Test misc commands:
        r.clear
        assert_equal( r.lines, [  ] )
        assert_equal( r.edited?, true )

        r.mark
        r.step
        assert_equal( r.line, 2 )
        r.unmark
        assert_equal( r.line, 1 )


        # ------------------------------------------------------------
        # Test file saving:

        ofile = 'test/output/test_file1.txt'
        r.copy( ofile )

        r2 = Patman.read( ofile )
        assert_equal( r.lines, r2.lines )

        r3 = Patman.read( ifile )
        r2.lines r3.lines
        r2.write

        assert( system( "diff #{ifile} #{ofile} " ) )

        FileUtils.rm_f ofile

    end

end