#!/usr/bin/perl

use strict;

BEGIN {
  $|  = 1;
  $^W = 1;
}

use lib "t/lib";
use SQLeetTest;
use Test::More;
use DBD::SQLeet;
use Data::Dumper;

# NOTE: It seems to be better to compare rounded values
# because stored coordinate values may have slight errors
# since SQLite 3.7.13 (DBD::SQLeet 1.38_01).

sub is_deeply_approx {
  my ($got, $expected, $name) = @_;
  my $got_approx      = [map { sprintf "%0.2f", $_ } @$got];
  my $expected_approx = [map { sprintf "%0.2f", $_ } @$expected];
  is_deeply($got_approx, $expected_approx, $name);
}

my @coords = (
  # id, minX, maxX, minY, maxY
  [1,  1,    200,  1,    200],  # outside bounding box
  [2,  25,   100,  25,   50],
  [3,  50,   125,  40,   150],
  [4,  25,   200,  125,  125],  # hor.  line
  [5,  100,  100,  75,   175],  # vert. line
  [6,  100,  100,  75,   75],   # point
  [7,  150,  175,  150,  175]
);

my @test_regions = (
  # minX, maxX, minY, maxY
  [75,   75,   45,   45],       # query point
  [10,   140,  10,   175],      # ... box
  [30,   100,  75,   75]        # ... hor. line
);

my @test_results = (
  # results for contains tests (what does this region contain?)
  [],
  [2, 3, 5, 6],
  [6],

  # results for overlaps tests (what does this region overlap with?)
  [1..3],
  [1..6],
  [1, 3, 5, 6]
);

BEGIN {
  if (!grep /ENABLE_RTREE/, DBD::SQLeet::compile_options()) {
    plan skip_all => 'RTREE is disabled for this DBD::SQLeet';
  }
}

use Test::NoWarnings;

plan tests => @coords + (2 * @test_regions)  + 4;

# connect
my $dbh = connect_ok( RaiseError => 1 );

# TODO: test rtree and rtree_i32 tables

# create R* Tree table
$dbh->do(<<"") or die DBI::errstr;
  CREATE VIRTUAL TABLE try_rtree
    USING rtree_i32(id, minX, maxX, minY, maxY);

# populate it
my $insert_sth = $dbh->prepare(<<"") or die DBI::errstr;
INSERT INTO try_rtree VALUES (?,?,?,?,?)

for my $coord (@coords) {
  ok $insert_sth->execute(@$coord);
}

# find by primary key
my $sql = "SELECT * FROM try_rtree WHERE id = ?";

my $idx = 0;
for my $id (1..2) {
  my $results = $dbh->selectrow_arrayref($sql, undef, $id);
  is_deeply_approx($results, $coords[$idx], "Coords for $id match");
  $idx++;
}

# find contained regions
my $contained_sql = <<"";
SELECT id FROM try_rtree
  WHERE  minX >= ? AND maxX <= ?
  AND    minY >= ? AND maxY <= ?

# Since SQLite 3.7.13, coordinate values may have slight errors.
for my $region (@test_regions) {
  my $results = $dbh->selectcol_arrayref($contained_sql, undef, @$region);
  is_deeply_approx($results, shift @test_results);
}

# find overlapping regions
my $overlap_sql = <<"";
  SELECT id FROM try_rtree
    WHERE    maxX >= ? AND minX <= ?
    AND      maxY >= ? AND minY <= ?

for my $region (@test_regions) {
  my $results = $dbh->selectcol_arrayref($overlap_sql, undef, @$region);
  is_deeply_approx($results, shift @test_results);
}
