package Hexed::Map;

use strict;
use warnings;
use include;

use Hexed::Util;
use Curses;

# Set up the window, but not the pad (yet).
sub init {
  my ($class, $dat) = @_;

  $dat->{Pad} = undef;
  $dat->{MapHeight} = $dat->{MapWidth} = 0;
  $dat->{OffY} = $dat->{OffX} = 0;  # Set up our offset pointers.
  die "How do we render!?\n" unless $dat->{Opts}{Render};
  $dat->{Render} = $dat->{Opts}{Render};

  delete $dat->{Opts};
  return bless $dat, $class;
}

# Swap in a new map with fixed dimensions.
sub setup {
  my ($win, $map) = @_;
  my $height = $map->height;
  my $width = $map->width;

  # Reset the offset pointers.
  $win->{OffY} = $win->{OffX} = 0;

  # Create a new pad and initialize it. (+1 due to ncurses offset)
  my $pad = newpad($height + 1, $width + 1);

  # Fill it up with the map's contents.
  foreach my $y (0 .. $height) {
    foreach my $x (0 .. $width) {
      my $draw = $win->{Render}->($map->{Map}[$y][$x]);
      $pad->addch($y, $x, $draw);
    }
  }

  # Set up a map handler so updating a tile tells us too.
  $map->{OnChange} = sub {
    my $self = shift;
    # Magic closureness ensures we see the reference to the window here!
    $win->_mod(@_);
  };

  $win->{MapHeight} = $height;
  $win->{MapWidth} = $width;
  $win->{Pad} = $pad;
  return 1;
}

# Modify a tile. Should be automatically called by the map interface.
sub _mod {
  my ($self, $y, $x, $new) = @_;
  my $draw = $self->{Render}->($new);
  $self->{Pad}->addch($y, $x, $draw);
}

# Redraw the window.
sub draw {
  my $self = shift;
  die "No map has been setup yet!\n" unless $self->{Pad};
  $self->{Win}->refresh if shift;   # fullscreen HexedUI stuff kills border

  $self->{Pad}->prefresh(
    $self->{OffY}, $self->{OffX},                # Where to start in the map?
    $self->{Y1}, $self->{X1}, $self->{Y2}, $self->{X2}  # Where on the screen?
  );
  # LIVECD THING: sleep or input
  #select(undef, undef, undef, 0.1);
  #getch;

  return 1;
}

# Shift the frame right.
sub right {
  my $self = shift;
  $self->{OffX}++ if $self->{OffX} + 1 <= $self->{MapWidth} - $self->{Width};
}

# Shift the frame left.
sub left {
  my $self = shift;
  $self->{OffX}-- if $self->{OffX} - 1 >= 0;
}

# Shift the frame up.
sub up {
  my $self = shift;
  $self->{OffY}-- if $self->{OffY} - 1 >= 0;
}

# Shift the frame down.
sub down {
  my $self = shift;
  $self->{OffY}++ if $self->{OffY} + 1 <= $self->{MapHeight} - $self->{Height};
}

42;
