#!/usr/bin/perl
use strict;
use warnings;

#
# See Bits.pm
#

## only for debugging
# use Data::Dumper;

#use Test::More qw(no_plan);

use Test::More tests => 30;
use_ok('Bits');

my $bits;
ok( defined($bits = Bits->new()),  "new blank Bits");

ok( $bits = Bits->new( raw => 'abcd' ),  "Bits raw 'abcd'");
# print "  " . $bits->as_text . "\n";
my $answer = '0110_0001_0110_0010_0110_0011_0110_0100';
ok( $bits->as_text eq $answer, "Bits as_text");
ok( $bits->as_binary eq '01100001011000100110001101100100',"Bits as_binary");
ok( $bits->as_hex eq '61626364', "Bits as_hex");
ok( $bits->as_raw eq 'abcd', "Bits as_raw");

ok( Bits->new( hex=>'aabbcd')->as_hex eq 'aabbcd', 
    "creation from hex");
ok( Bits->new( binary=>'00110011')->as_binary eq '00110011', 
    "creation from binary");
ok( Bits->new( binary=>'0011_0011')->as_binary eq '00110011',  
    "creation from binary with underbar");
ok( Bits->new( number=>123 )->as_number == 123,
    "creation from and conversion to number");

  ## odd bit lengths seem to work OK; hex or raw will pad to multiples of 8
  # print " five bits : \n";
  # $bits = Bits->new( binary=>'01011' );
  # print Dumper($bits);
  # print " as_binary : ", $bits->as_binary, "\n";
  # print " as_hex    : ", $bits->as_hex, "\n";
  # print " as_text   : ", $bits->as_text, "\n";

my $x = new Bits binary=>'0001_0101_1111';
#print " x = $x \n";
my $y = new Bits binary=>'0000_0101_1010';
#print " y = $y \n";
my $z = $x ^ $y;
#print " $x ^ $y = $z \n";
ok( $z->as_text eq '0001_0000_0101', "overloaded ^ is xor");
ok( "$z" eq '0001_0000_0101',        "stringification is as_text");

my $zz = $z->clone;
ok( "$z" eq "$zz", "clone as_text is same");
ok( $z->{array} != $zz->{array}, "clone's array ptr is different");
#print " z is '$z' with array " . $z->{array} . "\n";
#print " zz is '$zz' with array " . $zz->{array} . "\n";

my $original = '1101_0101';
$z = new Bits binary=>$original;
#print " z is '$z' \n";
$z = $z << 2;
#print " left(2) is '$z' \n";
$z = $z >> 3;
#print " right(3) is '$z' \n";
$z = $z << 1;
#print " left(1) is '$z' \n";
ok("$z" eq $original, "left and right shift");

my $first  = new Bits binary=>'1111_1111';
my $second = new Bits binary=>'0000_0000';
my $both = $first . $second;
ok( "$both" eq '1111_1111_0000_0000', 'concatenation with $x . $y');

ok( $both->size eq 16, "bits->size");

ok( "z is " . $z eq 'z is 1101_0101',      "string . Bits");
ok( $x . " is x" eq '0001_0101_1111 is x', "Bits . string");

#print  "z is " . $z. "\n";
#print $x . " is x \n";
$y = $z ^ $x;
ok( $y->as_text eq 'Oops: attempted Bits XOR on differing sizes', 
    "Bit xor with different lengths gives an error");

#print " z = " . Dumper($z);
#print " x = " . Dumper($x);
#print " y = " . Dumper($y);
#print "y is '$y'\n";

#print "x is $x\n";
#print "x is 0x" . $x->as_hex . "\n";
ok( $x->as_hex eq '15f', 'hex with odd number of nibbles');
#print "x is " . (0+$x) . "\n";
ok( (0+$x) == 351, 'as_number');
$x = new Bits binary=>'00011';
ok( "".$x->as_hex eq 
      'Oops - can only convert to hex if size is a multiple of 4',
    "as_hex error if not size % 4 == 0");

$x = new Bits binary=>'0011_1100';
# print " x->get($_) = '" . $x->get($_) . "'\n" for 0..7;
ok( $x->get(2) == 1, "bits->get(index)");

$x->set(12,7);
ok( $x->error, "set(index,value) with value not 0 or 1 is an error");
# print " x = '$x'.\n";   # error

$x = new Bits binary=>'0011_1100';
$x->set(12,1);
ok( $x->error, "set(index,value) with index outside range is an error");
# print " x = '$x'.\n";   # error

$x = new Bits binary=>'0011_1100';
$x->set(0,1);   # (index, value)
#print " x = '$x'.\n";
ok( $x->get(0) == 1, "bits->set(index,value)");

$x = new Bits binary=>'1001';
#print "x = '$x'\n";
$y = $x->permute(1,0,3,2);          # gives 0110
ok( "$y" eq '0110', "permute");
#print "y = '$y'\n";
$z = $x->permute(0,0,1,1,2,2,3,3);  # gives 11000011
#print "z = '$z'\n";
ok( "$z" eq '1100_0011', "permute with repeated indeces");
